Fonksiyonel programlama birçok farklı teknik içerir. Bazı teknikler yan etkilerle iyidir. Ancak önemli bir husus denklemsel akıl yürütmedir : Eğer aynı değerde bir fonksiyon çağırırsam, daima aynı sonucu alırım. Böylece bir işlev çağrısını döndürme değeri ile değiştirebilir ve eşdeğer davranış elde edebilirim. Bu, özellikle hata ayıklama sırasında program hakkında akıl yürütmeyi kolaylaştırır.
Fonksiyonun yan etkileri varsa, bu tam olarak geçerli değildir. Dönüş değeri fonksiyon çağrısına eşdeğer değildir, çünkü dönüş değeri yan etkileri içermez.
Çözüm, yan etkileri kullanmayı bırakmak ve bu etkileri dönüş değerinde kodlamaktır . Farklı diller farklı efekt sistemlerine sahiptir. Örneğin Haskell, IO veya Durum mutasyonu gibi belirli etkileri kodlamak için monad kullanır. C / C ++ / Rust dilleri, bazı değerlerin mutasyonuna izin vermeyen bir tür sistemine sahiptir.
Zorunlu bir dilde, bir print("foo")
işlev bir şey yazdırır ve hiçbir şey döndürmez. Haskell gibi saf işlevsel bir dilde, bir print
işlev aynı zamanda dış dünyanın durumunu temsil eden bir nesneyi alır ve bu çıktıyı gerçekleştirdikten sonra durumu temsil eden yeni bir nesne döndürür. Benzer bir şey newState = print "foo" oldState
. Eski eyaletten istediğim kadar yeni eyalet oluşturabilirim. Ancak, ana işlev tarafından yalnızca bir tanesi kullanılacaktır. Bu yüzden fonksiyonları zincirleyerek durumları birden çok eylemden sıralamam gerekiyor. Yazdırmak için foo bar
benzer bir şey söyleyebilirim print "bar" (print "foo" originalState)
.
Bir çıkış durumu kullanılmazsa, Haskell tembel bir dil olduğu için bu duruma giden eylemleri gerçekleştirmez. Tersine, bu tembellik sadece mümkündür, çünkü tüm efektler açıkça dönüş değerleri olarak kodlanmıştır.
Haskell'in bu rotayı kullanan tek yaygın olarak kullanılan işlevsel dil olduğunu unutmayın. Diğer fonksiyonel diller dahil. Lisp ailesi, ML ailesi ve Scala gibi yeni işlevsel diller cesaretini kırıyor, ancak yine de yan etkilere izin veriyor - bunlara zorunlu-fonksiyonel diller denilebilir.
G / Ç için yan etkiler kullanmak muhtemelen iyidir. Genellikle, G / Ç (günlük kaydı dışında) yalnızca sisteminizin dış sınırında yapılır. İş mantığınızda dış iletişim olmaz. Daha sonra bir dış kabukta saf G / Ç işlemi gerçekleştirirken, yazılımınızın çekirdeğini saf bir tarzda yazmak mümkündür. Bu ayrıca çekirdeğin vatansız olabileceği anlamına gelir.
Vatansızlık, artan mantıksallık ve ölçeklenebilirlik gibi bir dizi pratik avantaja sahiptir. Bu web uygulaması arka uçları için çok popüler. Her durum dışarıda, paylaşılan bir veritabanında tutulur. Bu yük dengelemeyi kolaylaştırır: Oturumları belirli bir sunucuya yapıştırmak zorunda değilim. Daha fazla sunucuya ihtiyacım olursa ne olur? Sadece bir tane daha ekleyin, çünkü aynı veritabanını kullanıyor. Bir sunucu çökerse ne olur? Bekleyen istekleri başka bir sunucuda yeniden yapabilirim. Tabii ki, hala - devlet veritabanında. Ama ben bunu açıkça belirttim ve çıkardım ve eğer istersem dahili olarak saf işlevsel bir yaklaşım kullanabilirdim.