C# İle Fonksiyonel Programlama - Map

Giriş

Önceki yazımızda fonksiyon delegelerinden bahsettik. Bu yazımızdan itibaren fonksiyonel programlama yöntemlerini C# ile uygulama yöntemlerinden bahsetmeye başlayacağız.

  • Map
  • Filter
  • Reduce

Map

Steven alttaki tweetiyle Map, Filter ve Reduce yöntemlerini çok güzel şekilde ifade etmiş:

  • Cook ismindeki fonksiyonumuz Girdi olarak [🌽, 🐮, 🐔] alıyor ve herbirini pişirerek [🍿, 🍔, 🍳]‘e dönüştürüyor.
  • isVegeterian filtresi [🍿, 🍔, 🍳] arasından vejeteryanler için olmayanları filtreliyor.
  • eat reduce fonksiyonu ise [🍿, 🍳] alıp …

Biraz Teori

Hafifçe teorik gidelim:

Elimizde bir f(x) fonksiyonu olsun.

f(x) = y

x, sıcaklık birimi Celcius olsun ve f(x) fonksiyonu, Celcius birimini Fahrenheit birimine çeviren bir fonksiyon olduğunda f(x) bir Map (dönüşüm) fonksiyonu diyebiliriz.

f(°C) = °F

C# Map Kullanımı

Map fonksiyonunun C# dilindeki karşılığı IEnumerable extension metodu olan Select fonksiyonudur. Bu yazımızda Select fonksiyonunu kullanmayacağız, benzerini kendimiz geliştireceğiz.

C# Map

Celcius ↔ Fahrenheit Dönüşüm Fonksiyonu

Celcius ↔ Fahrenheit dönüşüm fonksiyonundan yola çıkarak elimizdeki fonksiyonun bir adet girdisi ve bir adet çıktısı olmalı. Alttaki gibi dönüşüm fonksiyonumuz olduğunu farz edelim.

C# Function to Convert Celcius to Fahrenheit

C# Delegelerini Kullanarak Kendi Map Fonksiyonumuzu Yazalım

Önceki yazılarımızda Func<T, TResult> delegesinden bahsetmiştik. Bu dönüşüm fonksiyonumuzu delege ile temsil etmek istersek:

C# Delegate of Convert Celcius to Fahrenheit Function

Elimizdeki bir Celcius veri setini, Fahrenheit değerlerine çevirecek bir fonksiyon yazalım ve bunu delegeleri kullanarak yapalım.

Alternatif #1

Functional Alternative #1

Buradaki yaklaşım fonksiyonel programlama yöntemlerine uygun olmadı:

  1. fahrenheit fonksiyonu, parametreleri dışında global olan dış bir değişkene (convertCtoF) bağımlı. saf (pure) değil çünkü içeride kullanılan değerler parametrelerden alınmamış. Diğer ifadeyle hardcoded bir değer.

  2. convert fonksiyonuna direkt bağımlılık mevcut. Diğer ifadeyle tightly coupled convertCtoF fonksiyonu buraya parametre olara geçilebilmeliydi.

Çözüm, fonksiyonları delege olarak tanımlayarak low-level convertCtoF fonksiyonumuzu high level fahrenheit fonksiyonumuza parametre olarak geçmek.

Alternatif #2

Functional Alternative #2

Yeni fonksiyonumuza Func<Celcius, Fahrenheit> delege tipinde yeni bir parametre ekledik.Böylece bu delege tipine uyumlu herhangi bir fonksiyonu parametre olarak geçebileceğiz.

Kullanımı:

Usage

Genel amaçlı bir map fonksiyonu geliştirelim

Genel amaçlı bir map fonksiyonunu geliştirebilmek için elimizdeki hardcoded olan tip parametrelerini jenerik hale getirmemiz gerekli.

General usage map function implementation

Kullanımı:

Usage of implemented general usage map function

Yeni map fonksiyonumuzla beraber sıcaklık değer listelerini, diğer birimlere çevirecek fonksiyonları tek tek yazmak yerine map<T, TResult> fonksiyonunu kullanarak türetebileceğiz.

Örnek:

Usage of implemented general usage map function final

Sonuç

Bu yazımızda fonksiyon delegelerini kullanarak genel amaçlı bir map implementasyonu yazmaya çalıştık. Siz de bir code kata 1 uygulaması olarak ÖTV ve KDV hesaplayan fonksiyonlar yazabilir, bu fonksiyonları delege yardımıyla map fonksiyonu aracılığıyla kullanabilirsiniz.

Örnek bir uygulama içeren LINQPad dosyasını ekte bulabilirsiniz.

Edit

  • 2020/12/20 - İş arkadaşım Zişan, LINQ Pad dosyası örneği yerine dotnet fiddle önerdi. Linki aşağıya bırakıyorum, kaydırarak açabilirsiniz.

Bağlantılar

  1. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/select-clause
  2. https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.select?view=netcore-3.1
  3. MAP - dotnet fiddle

Resources