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ş:
Map/filter/reduce in a tweet:
— Steven Luscher (@steveluscher) June 10, 2016
map([🌽, 🐮, 🐔], cook)
=> [🍿, 🍔, 🍳]
filter([🍿, 🍔, 🍳], isVegetarian)
=> [🍿, 🍳]
reduce([🍿, 🍳], eat)
=> 💩
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.
1f(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.
1f(°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.
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# 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:
Elimizdeki bir Celcius veri setini, Fahrenheit değerlerine çevirecek bir fonksiyon yazalım ve bunu delegeleri kullanarak yapalım.
Alternatif #1
Buradaki yaklaşım fonksiyonel programlama yöntemlerine uygun olmadı:
fahrenheit
fonksiyonu, parametreleri dışındaglobal
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 ifadeylehardcoded
bir değer.convert
fonksiyonuna direkt bağımlılık mevcut. Diğer ifadeyletightly coupled
convertCtoF
fonksiyonu buraya parametre olara geçilebilmeliydi.
Çözüm, fonksiyonları delege olarak tanımlayarak low-level
convertCtoF
fonksiyonumuzu high levelfahrenheit
fonksiyonumuza parametre olarak geçmek.
Alternatif #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ı:
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.
Kullanımı:
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:
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.