Diyelim ki
fn(x),
x 'nin temel faktörlerinin bir listesini döndürmek gibi pahalı bir şey yapan saf bir işlevdir.
Ve diyelim ki
memoizedFn(x) adlı aynı işlevin not edilmiş bir versiyonunu yapıyoruz. Belirli bir girdi için her zaman aynı sonucu döndürür, ancak performansı artırmak için önceki sonuçların özel bir önbelleğini korur.
Resmi olarak,
memoizedFn(x) saf kabul edilir mi?
Ya da FP tartışmalarda) böyle bir işleve atıfta bulunmak için kullanılan başka bir ad veya nitelendirme terimi var mı? dönüş değerleri.)
Evet. Saf bir işlevin kaydedilmiş versiyonu da saf bir işlevdir.
Saflığın önem verdiği tek şey, işlevin dönüş değeri üzerindeki giriş parametrelerinin (aynı girdiyi geçmek her zaman aynı çıktıyı üretmelidir) ve küresel durumlarla ilgili tüm yan etkilerdir (örn. Terminale veya kullanıcı arabirimine veya ağa metin). . Hesaplama süresi ve fazladan bellek kullanımı işlev saflığı ile ilgisizdir.
Saf bir işlevin önbellekleri program tarafından hemen hemen görünmezdir; işlevsel bir programlama dilinin saf bir işlevi, işlevinin kaydedilmiş bir sürümüne otomatik olarak optimize etmesine izin verilirse, bunun yararlı olacağını belirleyebilir. Pratikte, hatırlamanın ne zaman faydalı olduğunu otomatik olarak belirlemek aslında oldukça zor bir sorundur, ancak bu optimizasyon geçerli olacaktır.
Wikipedia, bir "Pure Function" öğesini aşağıdaki özelliklere sahip bir işlev olarak tanımlar:
dönüş değeri aynı bağımsız değişkenler için aynıdır (yerel statik değişkenler, yerel olmayan değişkenler, değiştirilebilir referans bağımsız değişkenleri veya I/O cihazları).
Değerlendirmesinin herhangi bir yan etkisi yoktur (yerel statik değişkenlerin, yerel olmayan değişkenlerin, değişken referans argümanlarının veya G/Ç akışlarının mutasyonu yoktur).
Aslında, saf girdi aynı girdi verildiğinde aynı çıktıyı döndürür ve işlevin dışında başka hiçbir şeyi etkilemez. Saflık açısından, işlevin nasıl hesaplandığı önemli değildir aynı giriş verildiğinde aynı çıktıyı döndürdüğü sürece dönüş değeri.
Daha önce hesaplanan sonuçlarını önbelleğe alarak bir işlevi hızlandırmak için Haskell rutin olarak memoization kullanın gibi işlevsel olarak saf diller.
Evet, kaydedilmiş saf işlevler genellikle saf olarak adlandırılır. Bu özellikle, hafızaya alınmış, tembel olarak değerlendirilen, değişmez sonuçların yerleşik bir özellik olduğu Haskell gibi dillerde yaygındır.
Önemli bir uyarı var: not oluşturma işlevi iş parçacığı açısından güvenli olmalıdır, aksi takdirde iki iş parçacığı aramayı denediğinde bir yarış durumu elde edebilirsiniz.
“Tamamen işlevsel” terimini bu şekilde kullanan bir bilgisayar bilimcisinin bir örneği Conal Elliott tarafından yazılan bu blog yazısı otomatik notlama hakkında:
Belki de şaşırtıcı bir şekilde, notlaşma, tembel bir işlevsel dilde basit ve tamamen işlevsel olarak uygulanabilir.
Hakemli literatürde birçok örnek vardır ve onlarca yıldır vardır. Örneğin, 1995 tarihli bu yazı, “Gerçek Dünya Yapay Zeka Sistemlerinde Bir Otomatik Mühendislik Aracının Yazılım Mühendisliği Aracı Olarak Kullanılması” bugün saf işlev dediğimiz şeyi tanımlamak için bölüm 5.2'de çok benzer bir dil kullanmaktadır:
Notlama yalnızca gerçek işlevler için çalışır, yordamlar için çalışmaz. Diğer bir deyişle, bir işlevin sonucu, girdi parametreleri tarafından tam ve belirleyici olarak belirtilmezse, not kullanmak yanlış sonuçlar verir. Başarılı bir şekilde kaydedilebilen işlevlerin sayısı, sistem genelinde işlevsel bir programlama stilinin kullanılması teşvik edilerek artırılacaktır.
Bazı zorunlu diller benzer bir deyime sahiptir. Örneğin, C++ 'da bir
static const Değişkeni, değeri kullanılmadan önce yalnızca bir kez başlatılır ve hiçbir zaman değişmez.
Nasıl yaptığınıza bağlıdır.
Genellikle insanlar bir tür önbellek sözlüğünü değiştirerek ezberlemek isterler. Bu, eşzamanlılık konusunda endişelenmek, önbellek çok büyük büyümekten endişe etmek gibi saf olmayan mutasyonla ilgili tüm sorunlara sahiptir.
Ancak, kirli bellek mutasyonu olmadan not alabilirsiniz. Bir örnek bu cevap , burada bir
lengths argümanı ile kaydedilen değerleri harici olarak izliyorum.
Robert Harvey'nin sağladığı bağlantı 'da, yan etkileri önlemek için tembel değerlendirme kullanılır.
Bazen görülen başka bir teknik de, kedigil efektinin memoize işlevi gibi, notu açık bir
IO tipi bağlamında saf olmayan bir yan etki olarak işaretlemektir.
Bu sonuncusu bazen amacın onu ortadan kaldırmak yerine mutasyonu kapsüllemek olduğu noktasını getirir. Çoğu fonksiyonel programcı, safsızlığı açık ve kapsül haline getirmenin "yeterince saf" olduğunu düşünmektedir.
Bir terimin onu gerçekten saf bir işlevden ayırt etmek istiyorsanız, sadece "değişebilir bir sözlükle memoized" demek yeterli olduğunu düşünüyorum. Bu, insanların onu nasıl güvenle kullanacaklarını bilmelerini sağlar.
Genellikle, bir liste döndüren bir işlev, depolama tahsisi gerektirdiğinden ve bu nedenle başarısız olabileceğinden (örneğin, saf olmayan bir istisna atarak) hiç saf değildir. Değer türlerine sahip olan ve bir listeyi sınırlı boyutlu değer türü olarak gösterebilen bir dilde bu sorun olmayabilir. Bu nedenle örneğiniz muhtemelen saf değil.
Genel olarak, notlama hatasız bir şekilde yapılabilirse (örneğin, not edilen sonuçlar için statik olarak ayrılmış depolama alanı ve dil konuları kabul ederse bunlara erişimi kontrol etmek için dahili senkronizasyon ile), böyle bir işlevi dikkate almak mantıklıdır saf.
eyalet monad öğesini kullanarak yan etkiler olmadan not uygulayabilirsiniz.
[Durum monad] temel olarak S => (S, A) fonksiyonudur, burada S durumunuzu temsil eden tiptir ve A fonksiyonun ürettiği sonuçtur - Kediler Durum .
Sizin durumunuzda, devlet, kaydedilen değer veya hiçbir şey olmaz (ör. Haskell
Maybe veya Scala
Option[A]). Kaydedilen değer varsa
A olarak döndürülür, aksi takdirde
A hesaplanır ve hem geçiş durumu hem de sonuç olarak döndürülür.