Konu:
Fonksiyonel Programlama hala tam olarak anlamını kavrayamadığımız bir olgu. Bir de içinde 'fonksiyon' geçtiği için C gibi fonksiyon kullanan dillerle karıştırdığımız çok oluyor. Fonksiyonel programlama benim de yeni yeni anlamaya başladığım bir şey. Bu bağlamda Scala'nın babası olan Martin Oderski'nin verdiği Coursera'daki Functional Programming Principles in Scala adlı dersten çok faydalandım, size de tavsiye ederim. Bunun yanında bazı şeyleri de not olarak yazmak istiyorum. Kopyalamak pek beğendiğim bir yol değil ama internette bulduğumuz şeyi ikinciye bulmak bazen zor olabiliyor, hatta bazen silinmiş olabiliyor. O yüzden Ekşisözlük'te ssg'nin yazdığı bu entry'yi buraya kopyalamak ve bu anı ölümsüzleştirmek istiyorum.
fonksiyonel programlamada yan etki kavramiyla basa cikmak icin kullanilan konseptlerden biri. ama monad'i anlatmadan yan etki nedir ve yan etkiyle fonksiyonel programlamanin alip veremedigi ne var ona bakmak lazim.
genel olarak programlamada bir fonksiyonun kendisinden istenen degeri dondurmek disinda yol actigi gozlenebilir degisikliklerin tamamina yan etki deniyor. imperatif programlamada bu gayet dogal, mesela void'in varligi bile basli basina "bu fonksiyon tamamen yan etkilerden ibarettir" anlamina gelir. yan etkiye ornek verecek olursak:
int topla(int a, int b) { int toplam = a + b; return toplam; }yan etkiye sahip degilken (cunku mudahale edilen her sey fonksiyonun scope'u icindedir):
int topla(int a, int b) { int toplam = a + b; geneltoplam += toplam; return toplam; }yan etkiye sahiptir. fonksiyonun kendi scope'u disinda biseyleri degistirmektedir cunku. geneltoplam belli ki fonksiyon disinda bir yerde tanimlanmistir.
bir fonksiyonun yan etkiye sahip olup olmadigini anlamak basittir aslinda: fonksiyonu cagiran kodu direkt fonksiyonun dondurdugu degerle degistirince kod hic fark olmadan calismaya devam ediyor mu? ediyorsa bu yan etkiye yol acmayan fonksiyonlara "saf" (pure) fonksiyon deniyor.
amma velakin saf fonksiyonel programlamada "degisken" diye bir kavram olmadigindan ve her sey eninde sonunda bir fonksiyon oldugundan "degistirebileceginiz" degiskenler ve state'ler aslinda yok. yani yukardaki yan etkiye yol acan c# orneginin aslinda saf fonksiyonel bir dilde karsiligi yok. cunku saf fonksiyonel dillerde sizin degistirebileceginiz degiskenler yok. sadece ve sadece deger donduren fonksiyonlar var. bu da dili tasarlayanlarin mazosistliginden degil fonksiyonel programlamanin yapabilecegi bir yigin optimizasyon ve hata kontrolunun aslinda bu kisitlara dayaniyor olmasindan ileri geliyor. mesela saf fonksiyonlarin en buyuk avantaji, kendilerini dogru sirada cagirma zorunlulugu olmamasi, dolayisiyla derleyicinin isterse bunlari rahat rahat paralel (ornek erlang) ya da nasil hizli olacaksa o sirada calistirabilmesi ve lazy evaluation'a izin vermesi.
monad burada, yani saf fonksiyonel programlamaya "kontrollu yan etki" destegini katmak icin mevcut. mantigi da su: eger her seyi bir fonksiyonun donus degeri olarak tanimlayacaksak, o zaman state veya global degiskeni de fonksiyonun hem aldigi parametre hem de donus degeri olarak tanimlariz. mesela yan etkiye yol acan topla fonksiyonumuzu c# yapilari kullanarak soyle tanimlasaydik:
pairtopla(int a, int b, int geneltoplam) { int toplam = a + b; return new pair(toplam, toplam + geneltoplam); } state'i de parametre olarak alip donuste de yeni degerini, dondurmesi gereken degerle bir pakete toplayip donduren bir fonksiyon tanimlardik. boylece fonksiyonu cagiran fonksiyonlari soyle yazmak mumkun olur:
int biseylertoplavegeneltoplamiekranayaz() { console.writeline("genel toplam = {0}", topla(2,4,topla(3,5,0).second).second); }iste bu sekilde hic geneltoplam degiskeni tutmadan fonksiyon cagrilarinda state'i tutmayi basardik. monad da tam olarak bu teknigin adi oluyor. yani bir fonksiyonun giris ve cikis degerlerinde "yan etki"lerin tamamini da paslamada yapilan "enkapsulasyon" islemini saglayan fonksiyonel dil yapilarina monad deniyor.
aslinda monad sunu der: fonksiyon aldigi parametrelere ek olarak kainati parametre alir ve donus degeri olarak da kainatin yeni halini dondurur. cenabi hakkin yarattigi kainatin tamamini baska fonksiyona paslamak biraz uzun sureceginden sadece fonksiyonun yan etkilerle etkiledigi seyleri almak yeterlidir. o yuzden geneltoplam fonksiyonumuz bu konuda yeterlidir mesela.
yan etki illa ki degisken olmasi gerekmez. konsola cikti yazmak, loglama yapmak, ekrana pencere cikarmak vs vs, bunlarin hepsi gayetle gozlenebilir yan etkilerdir. elbette "konsolun icerigini yolla sonra geri tamamini al" yerine dissal olaylar icin (dosya islemleri, konsol, window, isletim sistemiyle genel munasebet), fonksiyonel diller genel gecer bir monad saglarlar. oradaki faraziya "bu cagridan sonra senin programin kendi tip sistemi disindaki her sey degisti"dir. o yuzden derleyici yan etkiye yol acan fonksiyonlari sirali olarak cagirir, paralel calismalarina izin vermez boylece kainati degistiren bir fonksiyonun ciktisi olan kainatin obur fonksiyona girdi olacagi garantilenir.
via https://twitter.com/fkadev/status/390340426290716672& https://eksisozluk.com/entry/22578104