Java'da İşlevsel Programlama mümkün mü? [kapalı]


42

Amazon.com Kitabevine göz atıyordum ve "Java Geliştiricileri için İşlevsel Programlama" kitabına rastladım .

Bazı çok temel Fonksiyonel Programlamaları biliyorum ve Java'da 3 senedir programlama yapıyorum.

İşlevsel Programlamanın Java'da bile mümkün olduğunu bilmek isterim?


2
Tarz mümkün, ancak ayrıntılı olması Java'nın sözdizimini göz önünde bulundurmak için çok fazla olabilir: functionaljava.org
Yuriy Zubarev

7
@ nCdy Neden JRuby'yi kontrol etmeliyim? lütfen daha fazla açıklama sağlayın.
Chiron

1
groovy :-) kontrol edin
Ant's

6
Sanırım bu, Java dili ile Java platformu arasındaki farkı ortaya çıkaran bir tür soru.
Thomas Owens

2
@ ThorbjørnRavnAndersen: "İşlevsel programlamanın" "tembel değerlendirme" ile tanımlandığını düşündüren nedir? Seçmek garip bir örnek gibi görünüyor ...
John Bartholomew

Yanıtlar:


70

"İşlevsel programlama" ve "mümkün" ile ne demek istediğinizi belirler.

İşlevsel bir paradigmayı takip eden şeyleri açıkça uygulayabilirsiniz. Bununla birlikte, Java dili bunun için sözdizimsel şeker sağlamaz, bu nedenle bazı şeyler en iyi şekilde sıkıcı olacak ve bazıları ise çok heyecan verici olacaktır.

Benzer şekilde, nesne yönelimli kodu, C gibi OO olmayan olarak bilinen bir dilde çok iyi yazabilirsiniz.

Java Kütüphaneleri

Bunu yapmanıza yardımcı olacak kütüphaneler var, zaten sizin için ayak işi yaparak ve gizli şeyleri gizleyerek:

Bunlar, FP kodlu bir dilden beklediğiniz gibi Java kodunu daha işlevsel bir yaklaşımla ve muhtemelen daha tanıdık bir sözdizimi ve anlamsal olarak yazmanıza izin verecektir. Sebep dahilinde, öyle.

JVM Dilleri

Ve tabii ki, Java'nın üstüne işlevsel bir dil uygulayabilirsiniz . Böylece onu FP diliniz olarak kullanabilirsiniz. İstediğinizden daha yüksek düzeyde bir soyutlamadır, ancak göreceli olarak bağlam içinde (burada biraz hile yapıyorum olsa da, verilmiş).

Örneğin, kontrol edin:

Daha Çok veya Daha Az İşlevsel JVM Dilleri

Tam olarak istediğin gibi olmasalar da, Java Platformuna aktarılmış ve sizi Java'nın nispeten eğlence amaçlı olmayan (evet, amaçlanan) doğasından kurtarıp, daha fazlasını verebilecek başka birçok dil var. esneklik. JRuby , Jython ve Rhino gibi dikkat çekici yarışmacılar (sırasıyla Ruby , Python ve JavaScript / ECMAScript için ), doğası gereği gerçekten işlevsel programlama dilleri olmasalar da, fonksiyonel programlama için ilginç bir potansiyel sunmaktadır. JetBrains ' Kotlin, açıkça kabul etmekle birlikte, işlevsel bir dil olmadığını, bazı işlevsel yapıları desteklediğini ve aynı zamanda görülmeye değer olduğunu kabul eder.

Daha fazla okuma

Ayrıca bu makaleleri veya videoları okumak veya izlemek isteyebilirsiniz:


2
Clojure kaynak kodu şimdi Github'da
Chiron

@ 1982 Efsanesi: Yorumunuzdan daha hızlıydım, resmi clojure.org sitesine bağlantıyı değiştirdim :) Ama bu kadar çabuk yakaladığınız için teşekkür ederiz! İnsanların hızlı tepki verdiğini görmek güzel.
haylem,

ABCL ( common-lisp.net/project/armedbear ) da var, ancak olgun / olgun ölçekte nerede düştüğü hakkında hiçbir fikrim yok ve bu bir Ortak Lisp uygulaması.
Vatine

@Vatine: İlginç, kesinlikle hiç duymamıştım. Hızlı bir görünüm ve onu ekleyecektir.
haylem

1
Bir languge o bir şeyler yapmaya çalıştıkları için Alan Perlis en terim "Turing Tarpit" aşk olabilir (tamamlanmadan turing olması nedeniyle) yapmak ama sadece teşebbüs edilmemelidir böyle acı ve karmaşıklığı ile.
saat

11

Bahsettiğiniz kitabı okuyorum. BTW gerçekten iyi.

Evet, Java'da işlevsel olmak mümkündür. Hangi dereceye ulaşabileceğinizi bilmiyorum ama birçok işlevsel programlama deyimi uygulayabilirsiniz.

En önemli şeylerden biri “devletleri değiştirmeyin” zihniyetini kodlamaya çalışmaktır.

Örneğin, değişmezliği sağlamak için son anahtar sözcüğü kullanırsınız. Bir veri yapısı kullanacaksanız, değişken veri yapılarını kodlamanız gerekir. Google Guava kütüphanesi zaten bunu yapıyor.

Ayrıca eşzamanlı programlama için, Akka çerçevesine (aktör modeli) güvenebilirsiniz.

JVM bayt kodunun (en azından henüz) Fonksiyonel programlama dilleri için çok önemli bir özellik olan Tail-call optimizasyonunu desteklemediğini belirtmekte fayda var.


“JVM bayt kodunun (en azından henüz) İşlevsel programlama dilleri için çok önemli bir özellik olan kuyruk çağrısı optimizasyonunu desteklemediğini belirtmekte fayda var.”: Ne demek istiyorsun? Scala'da TCO var.
Giorgio

@ Giorgio: Scala derleme zamanında TCO yapar.
scrwtp

@scrwtp: Bundan dolayı performans cezası var mı? Veya derleme zamanı TCO’nun dezavantajları nelerdir?
Giorgio

@ Giorgio: Demek istediğim, tıpkı Chiron'un daha önce de söylediği gibi, java bayt kodunun onu doğal olarak desteklemediği anlamına geliyor. İşlevsel diller, çevresinde özyinelemeli çağrıları döngüler halinde derleyerek çalışır, ancak bu JVM'yi değil, dil-> bayt kodu derleyicisinin bir özelliğidir.
scrwtp

@scrwtp: Chiron'un cevabı "JVM bayt kodunun (en azından henüz) İşlevsel programlama dilleri için çok önemli bir özellik olan kuyruk çağrısı optimizasyonunu desteklemediğini belirtmekte fayda var." JVM'de işlevsel bir dil uygulaması gibi görünmesi cezalandırılır, ancak (ve buna katılıyorum gibi) bu doğru değildir, çünkü kuyruk çağrısı optimizasyonu derlenmiş kodda simüle edilebilir. Bu yüzden Chiron'un ifadesine katılıyorum ancak bunu biraz yanıltıcı buluyorum.
Giorgio

6

Evet, herhangi bir turing-komple dil / uygulama ortamı kombinasyonunda mümkün olduğu gibi kesinlikle mümkündür . Ne yaptığınızı biliyorsanız, oldukça iyi performans göstermesini bile sağlayabilirsiniz.

Ne kadar mantıklı olduğundan emin değilim. Özellikle, özellikle aptalca olmadığını unutmayın (yani çok tuhaf görünecek, sıra dışı şeyler yapmanız ve normal Java'yı kullanan insanları şaşırtmanız gerekecek)

Örneğin, yeni bir işlev tanımlamak için tuhaf görünümlü bir kodla karşılaşacaksınız:

Function twoStrings=new Function() {
  public Object apply(Object param1) {
    // do something to param1 and return a result
  }
}

İşlevsel programlama yapmak için genellikle:

  • Birinci sınıf işlevler - "İşlev" inizi temsil eden ve işlevi bir veya daha fazla parametreye uygulayan bir "uygulama" yöntemine sahip soyut bir sınıf veya arabirim tanımlayarak Java'da oluşturmak kolaydır.
  • Kapaklar - son alanlarda depolanan kapama değerleri ile yukarıda fonksiyon nesnesinin bir örneğini oluşturun. Bunun için anonim bir iç sınıf kullanabilirsiniz.
  • Standart üst düzey işlevlerden oluşan bir kütüphane - bu daha zordur, ancak birkaç saat içinde basit bir işlevsel dili önyüklemek için hala kendiniz yazabilirsiniz. Eğer meraklısı bir şey istiyorsanız, insanların Java'da oluşturduğu diğer işlevsel kitaplıkları kontrol edebilirsiniz.

Yani bir egzersiz ve hatta ilginç bir hobi projesi olarak mümkün. Ancak JVM'nin / Java erişim kitaplıklarına erişim avantajlarını korurken ciddi fonksiyonel programlama yapmak istiyorsunuz, o zaman Clojure bence en iyi seçenek.

Gerçekten de, Clojure'un özü aslında Java'da yazıldığından beri, Java'da fonksiyonel programlama yapmak için ilginç ve ilginç bir örnek. Clojure kaynak kodu ilgilenenler için GitHub'da .


İlginçtir, IntelliJ IDEA'nın en son sürümünün bu anonim onesi'leri editörde görüntülemek için daha kompakt bir forma katlayacağını fark ettim. Gereksiz kıtlığı gizleme iyi bir iş yapar. Tabii ki tüm bunlar ilgisiz olacak Java 8 geliyor.
Ben Hardy

4

Java'da biraz işlevsel olmak mümkündür. Bunu yapmak çok acı verici . Onun yerine

myList.each { doSomething(it); }

Gibi bir şey var:

myList.each(new Function() { public void do(Object arg) { something(); }})

Ve gerçek fonksiyonel programlama istiyorsanız, birinci sınıf nesneler olarak kapatılan ve işlev gören başka bir dil seçin. Scala, Clojure, Groovy hepsi JVM'de çalışır ve eski Java sınıflarıyla etkileşime girebilir. .


İşlevsel programlama, isimsiz sınıflar yerine blok kullanmakla ilgili değildir. Java 8 bloklara sahip olacak, bu nedenle yayınlanan kodunuz daha şık görünecek ancak işlevsel programlama olmayacak.
Chiron

@ Efsane: Bunu anlıyorum ama açık bir şekilde açıklayamadım.
kevin cline

bu gözetim / anlayıştır. Herhangi bir dilde, SOMEWHERE işlevini tanımlamanız gerekir, o kısmı atlayamazsınız. Yani Java neredeyse özlü, tek yapmanız gereken Function nesnesini isimsiz yapmak. Bunu yapabilirsiniz: Function f = new Function () {public void do () {}}; .... sonra ... bu işlevi çağırın .... myMethodToCallAFunction (Function f) {f.do ()} ... işte bu, bros ve brolinis. başa çıkmak.
Alexander Mills,

3

Cevap, yanıltıcı bir “evet, elbette”, ancak bence birçok işlevsel dilde en önemli özelliklerden biri mükemmel tip sistem. Bunu asla Java'da kendiniz yönetemezsiniz.

Eğer bakmak için olağan şüpheliler Scala ve Clojure arasında tavsiye edebilir JVM I fonksiyonel programlar ve henüz kalmak yazmak istiyorsanız Frege . Frege, Haskell'e çok yakın olan bir sözdizimi ve tip sistemine sahiptir, ancak programlar doğrudan java koduna çevrilir ve diğer java kodlarıyla etkileşime girebilir.


2

Her türlü şey mümkün. C de nesne yönelimli programlama yapmak mümkündür; bu sadece çok iyi bir fikir değil.

Java FP için tasarlanmadı, bu yüzden her şeyi tamamen FP tarzında yapmaya çalışıyorsanız sorun yaşarsınız. Onunla çalışmak yerine, dille savaşıyor olacaksınız. Ve sadece dil değil - harika ücretsiz Java kütüphaneleri de var. Yani saf FP için gitmeyin; FP'nin arkasındaki fikirlerin bir kısmını alın ve bunları Java kodunuza entegre edin, ancak bunu tüm fikirlere yapamayacağınızı anlayın .


0

OpenJDK ekibi tarafından en yeni OpenJDK 8 ikili dosyalarını indirmeleri ve yeni lambda ifadeleri ve Koleksiyonlar API'sinde (diğerleri arasında) tanıtılan yeni işlevsel deyimlerle oynamaları için teşvik edilirsiniz. Net bir işlevsel tarzda programlayabilirsiniz. Bkz. "Java'da işlevsel programlama?" Guava, FunctionalJava ve LambdaJ gibi Java8 öncesi kütüphanelerle yapılan JDK8 Koleksiyonlar için.


-3

Mümkün görünebilir ancak tamamen işlevsel bir programlama olmayacak. Zorunlu programlama ile sonuçlanabilir.

Haylem'in dediği gibi olası işlevsel programlamayı neden kastettiğini sormak yok . İşte burada:

"İşlevsel programlama" ve "mümkün" ile ne demek istediğinizi belirler.

İşlevsel programlama farklı tanımlara veya anlamlara sahip olamaz, ancak birçok açıklaması olabilir.
OOP gibi, "OOP ile ne demek istiyorsun?" Diye sorabilir miyiz?
Kesinlikle çok fazla açıklama olacak ancak bu sadece OOP'un hedefi olan tek bir amaç için geçerli olacak.
Aynısı fonksiyonel programlama için de geçerlidir .

Fonksiyonel anlam dediğimiz zaman programlar fonksiyonlardan oluşur.
İşlevlerin rolü, değerlendirilen bir argüman / parametre döndürmektir (argüman değişkendir; işlev çağrılırken parametre, işlev bildiriminin bir parçası olan değişken iken).

Ayrıca aynı argümanlar iletildiğinde işlevler her zaman aynı sonucu verir. Bu şekilde, böcekleri önlemek veya gelecekteki böcekleri hata ayıklamak daha kolaydır. Fonksiyonel programlama ile global değişkeni değiştirmek gibi yan etkilerden kaçınabiliriz.

JavaScript’teki örnek:

function increment(lis){
    return lis.map(
        function (x){
            return x+2;
        }
    );
}

var myList = [4, 7, 2, 3];
console.log(increment(myList));
console.log(myList);

İşlev artışı, nesnenin içindeki her bir öğeye 1 değer ekler ve sonucu döndürür. MyList'in değeri değişmedi, ancak işlevleri çağırdığımızda o nesnenin öğelerine katma değeri gördük.

İşlevsel Programlamaya cevabım Java ile mümkün mü? , Java'da gerçek işlevsel programlamanın mümkün olmadığına inanıyorum. Çünkü java, zorunlu programlamayı genişlettiği ve bakım kolaylığı için geliştirdiği OOP olarak tasarlandı. Bir nesnenin durumu, değişken vb. Değiştiğinde, bu zaten zorunlu bir programlamadır.

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.