Yannis'in belirttiği gibi , daha önce olmayan dillerdeki üst düzey işlevlerin benimsenmesini etkileyen bir dizi faktör var. Sadece hafifçe dokunduğu önemli maddelerden biri çok çekirdekli işlemcilerin çoğalması ve bununla birlikte daha paralel ve eşzamanlı işlem yapma isteğidir.
Harita / filtre / azaltma işlevsel programlama tarzı, paralel bir programlamaya son derece uygundur, bu sayede programcının açık bir iş parçacığı kodu yazmadan çoklu çekirdeklerden kolayca yararlanmasını sağlar.
Giorgio'nun belirttiği gibi, işlevsel programlamanın sadece üst düzey işlevlerden daha fazlası vardır. İşlevler, artı bir harita / filtre / programlama düzenini azaltır ve değişmezlik, işlevsel programlamanın özüdür. Bunlar birlikte paralel ve eşzamanlı programlamanın güçlü araçlarını oluşturur. Neyse ki, birçok dil zaten bazı değişkenlik kavramını desteklemektedir ve programcılar, kitaplıkların ve derleyicinin eşzamanlı olmayan veya paralel işlemler oluşturmalarına ve yönetmelerine olanak tanıyan şeyleri değişmez olarak değerlendirebilirler.
Bir dile yüksek dereceli işlevler eklemek, eşzamanlı programlamayı basitleştirmede önemli bir adımdır.
Güncelleme
Loki'nin belirttiği endişeleri gidermek için daha ayrıntılı örnekler ekleyeceğim.
Bir widget koleksiyonundan geçen ve yeni bir widget fiyatları listesi oluşturan aşağıdaki C # kodunu göz önünde bulundurun.
List<float> widgetPrices;
float salesTax = RetrieveLocalSalesTax();
foreach( Widget w in widgets ) {
widgetPrices.Add( CalculateWidgetPrice( w, salesTax ) );
}
Geniş bir widget koleksiyonu veya hesaplama açısından yoğun bir CalculateWidgetPrice (Widget) yöntemi için bu döngü kullanılabilir çekirdeklerden hiçbirini iyi kullanmaz. Farklı çekirdekler üzerinde fiyat hesaplamaları yapmak, programcının açıkça iş parçacığı oluşturmasını ve yönetmesini, etrafta dolaşmasını ve sonuçları toplamasını gerektirir.
C #'ya yüksek dereceli fonksiyonlar eklendiğinde bir çözüm düşünün:
var widgetPrices = widgets.Select( w=> CalculateWidgetPrice( w, salesTax ) );
Foreach döngüsü, uygulama detaylarını gizleyerek Select yöntemine taşındı. Programcıya kalan tek şey, her bir elemana hangi işlevi uygulayacağınızı seçmektir. Bu, Seçim uygulamasının hesaplamaları parselel olarak gerçekleştirmesine ve programlayıcı katılımı olmadan tüm senkronizasyon ve iş parçacığı yönetimi kaygılarını ele almasına izin verir.
Ancak, elbette, Seç bu işi paralel olarak yapmaz. Değişmezliğin geldiği yer burasıdır. Select'in uygulanması, sağlanan işlevin (yukarıdaki CalculateWidgets) yan etkileri olmadığını bilmez. Bu fonksiyon, programın durumunu Seçim ve senkronizasyon görünümünün dışında değiştirerek her şeyi kırabilir. Örneğin, bu durumda salesTax'ın değeri hatalı olarak değiştirilebilir. Saf işlevsel diller değişmezlik sağlar, böylece Select (harita) işlevi hiçbir durumun değişmediğinden emin olabilir.
C #, PLINQ'u Linq'e alternatif olarak sağlayarak gider. Şunun gibi olurdu:
var widgetPrices = widgets.AsParallel().Select(w => CalculateWidgetPrice( w, salesTax) );
Bu, bu çekirdeklerin açık yönetimi olmadan, sisteminizin tüm çekirdeklerini tam olarak kullanır.