İşlevsel bir programlama dili ne zaman kullanılır?


90

Hangi durumlarda, C ++, C # veya Java gibi daha ayrıntılı nesne yönelimli bir dil yerine işlevsel bir programlama dili kullanmayı seçmeliyim?

İşlevsel programlamanın ne olduğunu anlıyorum, gerçekten anlamadığım şey ne tür problemler için mükemmel bir çözümdür?



2
Her zaman. Ya da en azından asla.
Shelby Moore III

1
Lambdas ile C # sınırda işlevseldir.
JD

Yanıtlar:


51

Benim görüşüme göre, işlevsel diller esas olarak iki şey için iyidir: Oyun AI'leri ve matematiksel hesaplamalar. Güzel liste manipülasyonları nedeniyle (en azından Lisp ve Scheme'de) ve sözdizimi nedeniyle matematiksel hesaplamalar için oyun yapay zekalarında iyidir. Scheme, Lisp ve Haskell, matematiksel hesaplamaları okumayı kolaylaştıran bir sözdizimine sahiptir. Eklemem gereken son şey, işlevsel dillerin gerçekten eğlenceli diller olmasıdır. Scheme kursum en çok eğlendiğim kurslardan biriydi.


2
Scheme'de aldığım derleyici sınıfının ilk haftasında beynimin patlamak istediğini
anladıktan

1
Matematiksel hesaplamalar için hangi işlevsel dilleri kullandınız?
Jules

8
Ayrıca derleyiciler! Haskell'de derleyiciler yazan insanların "bir daha asla zorunlu dilde bir derleyici yazmayacaklarını" söylediklerini duydum.
ShreevatsaR

1
julesjacobs: Basit matematiksel hesaplamaları çözmek için biraz haskell ve Scheme kullandım. Bu dillerde hiç iyi değilim, bu yüzden daha karmaşık sorunları çözmek için gideceğim bir yol var. Şimdiye kadar onları yeterince hızlı yapamıyorum.
martiert

96

Bununla ilgili biraz araştırma yaptım ve işlevsel bir dil kullanmak için nedenler listesine CONCURRENCY ekleyebileceğimi düşündüm. Gördüğünüz gibi yakın gelecekte işlemci hızı aynı cpu teknolojisini kullanarak artamayacak. Mimarinin fiziği buna izin vermez.

Eşzamanlı işlemenin geldiği yer burasıdır.

Ne yazık ki çoğu OOP dili, veriler arasındaki karşılıklı bağımlılıklar nedeniyle aynı anda birden fazla işlemciden yararlanamaz.

Tamamen işlevsel programlama dillerinde, bilgisayar aynı anda iki (veya daha fazla) işlevi çalıştırabilir çünkü bu işlevler dış durum bilgilerini değiştirmez.

İşte hoşunuza gidebilecek işlevsel programlama hakkında mükemmel bir makale .


38
Çoğu OO dilinin keyfi olarak çok sayıda işlemciden yararlanamayacağını söylemem. Bir programın aynı anda birçok işlemciden verimli ve güvenilir bir şekilde yararlanabilmesi için, bu programın çoğu hesaplama yoğun kod biriminin saf işlevler gibi davranacağı şekilde organize edilmesi gerektiğini söyleyebilirim. Çoğu dilde bu şekilde bir program düzenlemek mümkündür. İşlevsel dillerde yapmak, zorunlu (nesne yönelimli dahil) dillerde olduğundan daha kolaydır.
Zak

2
Bu makaleyi bağladığınız için teşekkür ederiz. Benim için olayları açıklamaya gerçekten yardımcı oldu.
abc123

13

Bir arkadaşım, üniversite hocalarından birinin aşağıdaki gibi bir şey söylediğini aktardı:

Üstte veri türleri ve sol tarafta bu veri türleri üzerindeki işlemler ile bir ızgara çizin. Izgarayı dikey olarak dilimlerseniz, OO yapıyorsunuz; ızgarayı yatay olarak bölerseniz, FP yaparsınız.

Cevabım, FP'nin OO kadar geniş bir uygulama yelpazesiyle programlamaya tamamen uygun bir yaklaşım olduğudur. Herhangi bir programlama dili seçimi tartışmasında olduğu gibi, bence daha önemli sorular:

  1. Yeni bir notasyon ve yeni bir düşünme şekli öğrenmek için yatırım yapacak vaktiniz var mı?
  2. Düşündüğünüz dillerden hangisinde, bir çarkı yeniden icat ederken takılıp kalmayacağınız yeterince zengin kitaplıklar var?

İlk soruya gelince, bunu öncelikle öğrenme değeri için yapıyorsanız , çok çeşitli destek materyalleri (kitaplar, makaleler, aktif topluluk, vb.) Nedeniyle Haskell'e bakmanızı öneririm .

İkinci soruya gelince, Haskell'in güzel bir kütüphane yelpazesi var (bazıları diğerlerinden daha olgun olsa da), ancak Scala (JVM'de çalışan hibrit OO işlevli bir dil), kademeli olarak işlevsel stile geçebileceğiniz avantajlara sahip. ve kullanabileceğiniz Java ile erişilebilen kitaplıkların tamamına sahipsiniz.


Üniversitede Scheme öğrendim, bu yüzden sadece deneyim için fonksiyonel programlamayı öğrenmek istemiyorum. Pratik nedenlerden dolayı işlevsel bir dil öğrenmeyi tercih ederim.
Alex Baranosky

9

Pratik olarak PP'de yapabileceğiniz her şey FP'de ve aynı şey tersi olarak yapılabilir. Bu sadece bir şeyi kodlamanın başka bir yolu - soruna başka bir bakış açısı ve onu çözmenin farklı bir yolu.

Ancak, pek çok kişi FP kullanmadığından, sorun daha çok iyi kütüphanelerin eksikliği, taşınabilirlik / sürdürülebilirlik (çünkü bakımcının C ++ ile yazılmış bir şeyi anlama şansı Scheme'den daha yüksektir) ve dokümantasyon ve topluluk eksikliğidir. Bazı dokümanlar olduğunu biliyorum, ancak bunu C ++, C # veya Java ile karşılaştırın ve ne demek istediğimi anlayacaksınız.

Bununla birlikte, gerçekten FP yapmak istiyorsanız, bu stili C ++ ve C # 'da bile kullanabilirsiniz. Elbette, standart kitaplığı kullanırsanız% 100 FP olmayacaktır. Ne yazık ki, C # 'nin işlevsel programlama ile kullanılmak üzere optimize edildiğini düşünmüyorum ve muhtemelen birçok performans sorunu yaratacaktır.

Bu daha öznel bir gönderi, benim FP hakkında düşündüğüm şey. Kesin bir beyan değildir.


8
"Pratikte PP'de yapabileceğiniz her şey FP'de yapılabilir" - Aslında, tam olarak her şeydir.
BlueRaja - Danny Pflughoeft

2
@BlueRaja - Turing Tamlığı'ndan mı bahsediyorsunuz? Eğer öyleyse, söyledikleriniz takip etmez. Örneğin, Conway'in Game of Life is Turing Complete, ancak C'de olduğu gibi bir ekran kartı sürücüsü yazmak için kullanamazsınız. Aynı şekilde Haskell'de yazılmış en son oyunlardan hiçbirini görmüyorum. FP'de yapabilir! = Teorik olarak bir teorik FP'de yapabilir.
Luigi Plinge

@Luigi Plinge BlueRaja ile aynı fikirdeyim. Haskellers, Haskell'de yazılmış bazı Linux sürücülerini tartışıyor. Bir bağlantım yok, ancak Haskell'de bir işletim sisteminin yazıldığını da duydum (olası diğer işlevsel diller de). Oyunlara gelince, en son oyunların C # veya Java ile yazıldığını görmüyorum, bunun için kullanılamayacaklarını mı ima ediyorsunuz? Her neyse, FP ile yazılmış bir oyun örneği. Ayrıca, bağlantılarımın çoğunun PURELY işlevsel bir dil olan Haskell olduğunu unutmayın.
austinprete

@PardonMyRhetoric Açıkçası Haskell'de oyun yazabilir ve herhangi bir hesaplama yapabilirsiniz, ancak hız birkaç kat daha yavaş ve bellek kullanımı daha yüksek olacaktır. Bu nedenle, BlueRaja'nın ifadesine karşı bir örnek, FP'de "C'deki kadar hızlı ve çok bellek kullanan bir oyun" yazamayacağınızdır. Bu gerçekten pratik bir mesele, bilgiçlik taslayan bir numara değil (ve FP'ye hiç de basmıyorum - şu anda Scala'yı kodluyorum!)
Luigi Plinge

1
@PardonMyRhetoric Ayrıca deyimsel FP olması gerekir. Gördüğünüz, C'nin performansına yaklaşan Haskell performansı veren kriterler, çoğu Haskell programcısının yazamayacağı "düşük seviyeli" tek bir üslupta yazılmıştır. Örneğin, sadece Haskell kod çıktınızı yaparak ve C kodunu derleyerek benzer bir performans elde edebilirsiniz. Gerçi anlamsız. Bununla ilgili pratik bir konu, "yapabilirsin" ve "yapılabilir / yapılabilir" ile ilgilidir. Bir şey çok zorsa, teoride mümkün olup olmadığı (ve kim için "mümkün"?) Pek de önemli değildir.
Luigi Plinge

4

İşlevsel diller birçok durumda iyidir. Belirli bir işlevsel dilin kütüphanelerine bağlıdır.

"Nesne yönelimli bir programlama dili ne zaman kullanılır?" Sorusuna nasıl cevap verirsiniz?


1
"Nesne yönelimli bir programlama dili ne zaman kullanılır?" Herhangi bir şeyi sayısal olarak modellemek istediğinizde, diğer yandan fp'nin sezgisel asnswer olacağı bir problem arıyordum, hala arıyorum, bu yazıyı böyle buldum.
jimjim

@Arjang, sanırım fonksiyonel programlama, çıktı oluşturmak için yalnızca girdiye ihtiyaç duyan hesaplama uygulamalarında muazzam bir kullanım bulacaktır.
Değişebilirlik

3

Bu oldukça öznel bir soru olsa da, işlevsel dillerin alana özgü dilleri ayrıştırmak için çokça kullanıldığını eklemek isterim ; işlevsel doğası gramerleri ayrıştırmaya çok uygundur.


2
DSL'leri ayrıştırmak mı? Lisp makroları ve benzerleri ile DSL'lerin Lisp programları tarafından ayrıştırılacak bir şey değil , makrolar olarak uygulandığını düşündüm . Lisp dışı dillerle YMMV. :-P
Chris Jester-Young

1

Gördüğüm kadarıyla, bu işlevsellikten çok bir zevk meselesi (kelime oyunu amaçlanmadı). Her iki dil stili hakkında da onu belirli görevlerde doğası gereği daha iyi veya daha kötü yapan hiçbir şey yoktur.


2
@JonHarrop - Bunu detaylandırmak ister misin? Bunu o kadar açık bulmuyorum ve insanları daha az güçlendirici olmanın dışında oy verdiğiniz izlenimini bırakırsanız çok yazık olur.
TED

1
ML ailesi, ağaçları manipüle etmek için desen eşleştirme gibi sofistike dil özelliklerinin eklenmesiyle (örneğin ifade ağaçları) özellikle metaprogramlama için üretildi. Sonuç olarak, bu dil ailesi doğası gereği bu özel görevde çok daha iyidir.
JD

1
@JonHarrop - Bunu kabul edeceğim. Bununla birlikte, genel olarak işlevsel dillerden değil, ML'den bahsediyorsunuz. DSL'lere büyük bir inancım var, bu nedenle tam olarak tasarlandığı görev için belirli bir dili kullanmaya karşı çıkmayacağım.
TED

Bugün, kalıp eşleştirme OCaml, F #, Scala, Haskell, Clojure ve Erlang dahil hemen hemen tüm işlevsel dillerde bulunur. Örneğin, son zamanlarda matematiğe odaklanan bir müşteri için ısmarlama bir iş kuralları motoru oluşturdum. Bu 1.000 satır F # ve ağırlıklı olarak bir tercümandır. Kalıp eşleştirme sayesinde sözcük oluşturma, ayrıştırma, tür denetimi ve girişi yorumlama çok daha kolaydır.
JD

@JonHarrop .. ama hepsi değil. Fonksiyonel dillerin doğasında bulunan bir özellik değil, sorunun sorduğu da buydu.
TED

1

Genel olarak, bir sorunun çözümünü ifade etmenin en kolay olduğu dili kullanın. Fonksiyonel programlama için bu, bir problemin çözümünün fonksiyonlar açısından kolayca ifade edildiği zamandır , dolayısıyla adı. Genellikle matematiksel işlemler, AI, örüntü eşleştirme için iyidir; genel olarak, bir cevap almak için uygulanması gereken bir dizi kurala bölünebilecek herhangi bir şey. Yalnızca probleminizi yeterince analiz ettikten sonra kullanılacak "en iyi" dili gerçekten belirleyebilirsiniz. Sözde kodun işe yaradığı yer burasıdır. Kendinizi FP'ye benzeyen sözde kod yazarken bulursanız, FP kullanın.

Elbette, tüm programlama dilleri işlevsel olarak eşdeğerdir, bu nedenle hangi problemleri çözebileceğiniz açısından hangisini seçtiğiniz önemli değildir. Ana etkiler, kodlama verimliliği ve doğruluğu ve bakım kolaylığı açısından olacaktır.

Ayrıca akıllıca tasarlanmış API'ler aracılığıyla OO dillerinde FP'yi taklit etmenin mümkün olduğunu unutmayın. Örneğin, FP DSL'i simüle etmek için yöntem zincirleme kullanan çok sayıda Java kitaplığı (JMock bir örnektir) gördüm. Ardından aşağıdaki gibi yapılar göreceksiniz:

logger.expects(once()).method("error") .with( and(stringContains(action),stringContains(cause)) );

Bu, esasen sahte bir nesnedeki bazı arama sıralarının doğru olup olmadığını belirlemek için değerlendirilen bir işlev oluşturur. (örnek http://www.jmock.org/yoga.html adresinden çalındı )

Diğer OO dillerindeki diğer FP benzeri sözdizimi, Ruby'de olduğu gibi kapanışların kullanılmasıdır.


2
"... Çözebileceğiniz problemler açısından hangisini seçtiğiniz gerçekten önemli değil". Sadece probleminizi çözmek için sonsuz zamanınız ve paranız varsa.
JD

0

Önceki yazıların doğru olduğunu düşünüyorum burada kısa bir liste, fonksiyonel programlama aşağıdakiler için mükemmel bir çözüm:

  • vatansız işlem
  • ML (Makine Öğrenimi) dahil matematiksel denklemler
  • değişmez süreçler
  • ölçeklenebilir eşzamanlılık istediğinizde
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.