Apakah Pemrograman Fungsional dimungkinkan di Jawa? [Tutup]

42

Saya sedang menelusuri Toko Buku Amazon.com dan saya menemukan buku "Pemrograman Fungsional untuk Pengembang Java" .

Saya tahu beberapa Pemrograman Fungsional yang sangat dasar dan telah pemrograman di Jawa selama 3 tahun.

Saya ingin tahu apakah Pemrograman Fungsional dimungkinkan di Jawa?

Vinoth Kumar CM
sumber
2
Gaya ini mungkin tetapi verbositasnya bisa terlalu besar untuk diberikan mengingat sintaksis Java: functionaljava.org
Yuriy Zubarev
7
@nCdy Mengapa memeriksa JRuby? tolong berikan penjelasan lebih lanjut.
Chiron
1
periksa groovy :-)
Semut
6
Saya pikir ini adalah jenis pertanyaan yang menimbulkan perbedaan antara Java-the-language dan Java-the-platform.
Thomas Owens
2
@ ThorbjørnRavnAndersen: Apa yang membuat Anda berpikir bahwa "pemrograman fungsional" didefinisikan oleh "evaluasi malas"? Tampaknya ini contoh yang aneh untuk dipilih ...
John Bartholomew

Jawaban:

70

Itu tergantung apa yang Anda maksud dengan "pemrograman fungsional" dan "mungkin".

Anda jelas dapat menerapkan hal-hal berikut dengan paradigma fungsional. Namun bahasa Jawa tidak menyediakan gula sintaksis untuk itu, jadi beberapa hal akan sangat membosankan, dan beberapa yang lain akan sangat misterius.

Demikian pula, Anda dapat menulis kode berorientasi objek dengan sangat baik dalam bahasa yang dikenal sebagai non-OO, seperti C.

Perpustakaan Java

Ada perpustakaan yang dapat membantu Anda melakukan ini, dengan sudah melakukan kerja keras untuk Anda dan menyembunyikan hal-hal misterius:

Ini akan memungkinkan Anda untuk menulis kode Java dengan pendekatan yang lebih fungsional dan mungkin lebih sintaksis dan semantik, seperti yang Anda harapkan dari bahasa kompeten FP. Dalam alasan, itu.

Bahasa JVM

Dan jelas, Anda dapat menerapkan bahasa fungsional di atas Jawa. Sehingga Anda dapat menggunakan yang itu sebagai bahasa FP Anda. Yang sedikit lebih tinggi dari abstraksi daripada apa yang Anda minta, tetapi relatif dalam konteks (meskipun saya sedikit curang di sini, memang begitu).

Misalnya, lihat:

Bahasa JVM Lebih-atau-Kurang Fungsional

Walaupun mereka mungkin tidak persis seperti yang Anda inginkan, ada sejumlah bahasa lain yang telah diangkut ke Java Platform dan yang mungkin membebaskan Anda dari sifat Java yang relatif tidak begitu menyenangkan (ya, pun intended) dan sudah memberi Anda lebih banyak fleksibilitas. Pesaing terkenal seperti JRuby , Jython dan Rhino (masing-masing untuk Ruby , Python dan JavaScript / ECMAScript ) juga menawarkan potensi yang menarik untuk pemrograman fungsional, meskipun mereka pada dasarnya tidak benar-benar bahasa pemrograman fungsional secara alami. Kotlin JetBrains, Meskipun dengan jelas mengakui itu bukan bahasa fungsional, memang mendukung beberapa konstruksi fungsional dan juga patut dilihat.

Bacaan lebih lanjut

Anda mungkin juga ingin membaca atau menonton artikel atau video ini:

haylem
sumber
2
Kode sumber clojure
Chiron
@The Legend of 1982: Saya lebih cepat dari komentar Anda, saya sudah mengubah tautan ke situs resmi clojure.org :) Tapi terima kasih sudah menangkapnya begitu cepat! Senang melihat orang bereaksi cepat.
haylem
Ada juga ABCL ( common-lisp.net/project/armedbear ), tapi saya tidak tahu di mana itu jatuh pada skala dewasa / tidak dewasa dan itu adalah implementasi Common Lisp.
Vatine
@Vatine: menarik, sama sekali tidak pernah mendengarnya. Akan memiliki tampilan cepat dan menambahkannya.
haylem
1
Saya suka istilah Alan Perlis "Turing Tarpit" untuk mencoba melakukan sesuatu yang bisa dilakukan oleh seekor languge (karena turingnya lengkap) tetapi hanya dengan rasa sakit dan kompleksitas yang tidak boleh dicoba.
bruce
11

Saya membaca buku yang Anda sebutkan. Ini adalah BTW yang sangat bagus.

Ya, mungkin untuk berfungsi di Jawa. Saya tidak tahu sampai sejauh mana Anda dapat mencapainya tetapi Anda dapat menerapkan banyak idiom pemrograman fungsional.

Salah satu hal terpenting adalah mencoba kode dengan mentalitas "Don't mutate state".

Misalnya Anda menggunakan kata kunci terakhir untuk mencapai keabadian. Jika Anda akan menggunakan struktur data maka Anda harus kode dalam struktur data abadi. Perpustakaan Google Guava sudah melakukan ini.

Juga untuk pemrograman bersamaan, Anda dapat mengandalkan kerangka Akka (model aktor).

Perlu disebutkan bahwa bytecode JVM tidak mendukung (setidaknya belum) optimasi Tail-call, fitur yang sangat penting untuk bahasa pemrograman fungsional.

Chiron
sumber
"Perlu disebutkan bahwa bytecode JVM tidak mendukung (setidaknya belum) optimasi Tail-call, fitur yang sangat penting untuk bahasa pemrograman fungsional.": Apa maksud Anda? Scala memang memiliki TCO.
Giorgio
@Iorgio: Scala melakukan TCO pada waktu kompilasi.
scrwtp
@scrwtp: Apakah ada penalti kinerja karena itu? Atau apa kerugian dari TCO waktu kompilasi?
Giorgio
@Iorgio: Apa yang saya maksud adalah bahwa bytecode java tidak mendukungnya secara asli, seperti yang Chiron nyatakan sebelumnya. Bahasa fungsional bekerja di sekitarnya, mengkompilasi panggilan rekursif ke dalam loop, tetapi ini adalah fitur dari kompiler bytecode bahasa->, bukan JVM.
scrwtp
@scrwtp: Jawaban Chiron menyatakan "Perlu disebutkan bahwa bytecode JVM tidak mendukung (setidaknya belum) optimasi Tail-call, fitur yang sangat penting untuk bahasa pemrograman fungsional." membuatnya terdengar seperti implementasi bahasa fungsional pada JVM yang dihukum tetapi (dan kami sepertinya setuju dengan ini) ini tidak benar karena optimasi panggilan ekor dapat disimulasikan dalam kode yang dikompilasi. Jadi saya setuju dengan pernyataan Chiron tetapi saya merasa sedikit menyesatkan.
Giorgio
6

Ya, sangat mungkin , dengan cara yang sama dimungkinkan dalam kombinasi bahasa / lingkungan eksekusi turing-complete. Anda bahkan dapat membuatnya bekerja dengan cukup baik jika Anda tahu apa yang Anda lakukan.

Tidak yakin seberapa masuk akal itu. Secara khusus, ketahuilah bahwa itu tidak terlalu idiomatis (yaitu akan terlihat sangat aneh, Anda harus melakukan beberapa hal yang tidak konvensional dan membingungkan orang-orang yang terbiasa dengan Jawa biasa)

Anda akan berakhir dengan beberapa kode yang tampak aneh, misalnya untuk mendefinisikan fungsi baru:

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

Untuk melakukan pemrograman fungsional yang biasanya Anda butuhkan:

  • Fungsi kelas satu - mudah dibuat di Jawa dengan mendefinisikan kelas abstrak atau antarmuka yang mewakili "Fungsi" Anda dan memiliki metode "terapkan" yang menerapkan fungsi ke satu atau lebih parameter.
  • Penutupan - buat instance objek fungsi Anda di atas dengan nilai-nilai tertutup yang disimpan dalam bidang terakhir. Anda dapat menggunakan kelas dalam anonim untuk ini.
  • Pustaka fungsi tingkat tinggi standar - ini lebih rumit, namun Anda masih dapat menulis sendiri untuk mem-bootstrap bahasa fungsional sederhana dalam beberapa jam. Jika Anda menginginkan sesuatu yang lebih menarik, Anda dapat melihat perpustakaan fungsional lain yang telah dibangun orang di Jawa.

Jadi itu mungkin sebagai latihan dan bahkan proyek hobi yang menarik. Tetapi Anda benar-benar ingin melakukan pemrograman fungsional yang serius sambil mempertahankan keunggulan JVM / mengakses perpustakaan Java maka Clojure sejauh ini merupakan pilihan terbaik menurut pendapat saya.

ps karena inti dari Clojure sebenarnya ditulis di Jawa, itu sebenarnya contoh kasus yang sangat menarik tentang bagaimana melakukan pemrograman fungsional di Jawa sambil menyembunyikan detail berantakan di balik sintaksis bahasa modern baru yang bagus. Kode sumber Clojure ada di GitHub untuk mereka yang tertarik.

mikera
sumber
Menariknya, saya perhatikan bahwa versi terbaru IntelliJ IDEA akan melipat yang anonim ini menjadi bentuk yang lebih ringkas untuk ditampilkan di editor. Apakah pekerjaan yang layak cukup menyembunyikan persembunyian berlebihan. Tentu saja semua ini tidak relevan bagi Jawa 8.
Ben Hardy
4

Dimungkinkan untuk menjadi agak fungsional di Jawa. Melakukan hal itu sangat menyakitkan . Dari pada

myList.each { doSomething(it); }

Anda memiliki sesuatu seperti:

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

Dan jika Anda ingin pemrograman fungsional sejati, dengan penutupan dan berfungsi sebagai objek kelas satu, pilih bahasa lain. Scala, Clojure, Groovy semuanya berjalan pada JVM dan dapat berinteraksi dengan kelas-kelas Java yang lama. .

kevin cline
sumber
Pemrograman fungsional bukan tentang menggunakan blok, bukan kelas anonim. Java 8 akan memiliki blok, sehingga kode yang Anda posting akan terlihat lebih elegan tetapi tidak akan menjadi pemrograman fungsional.
Chiron
@ Legenda: Saya mengerti itu, tapi ternyata tidak menjelaskannya dengan baik.
kevin cline
ini adalah pengawasan / kekurangan. dengan bahasa apa pun, Anda harus benar-benar mendefinisikan fungsi DI MANA SAJA, Anda tidak dapat melewati bagian itu. Jadi Java hampir ringkas, yang harus Anda lakukan adalah membuat objek Function menjadi tidak sama. Anda dapat melakukan ini: Function f = Function baru () {public void do () {}}; .... lalu ... panggil fungsi itu .... myMethodToCallAFunction (Function f) {f.do ()} ... itu saja, bros dan brolinis. menghadapinya.
Alexander Mills
3

Jawabannya adalah tegas, "ya, tentu saja", namun menurut saya salah satu fitur paling penting dalam banyak bahasa fungsional adalah sistem tipe yang sangat baik. Anda tidak akan pernah bisa mengelola ini di Jawa sendiri.

Jika Anda ingin menulis program fungsional dan tetap dengan JVM saya dapat merekomendasikan di antara tersangka Scala dan Clojure untuk melihat Frege . Frege memiliki sintaks dan tipe sistem yang sangat dekat dengan Haskell, tetapi program diterjemahkan langsung ke kode java dan dapat berinteraksi dengan kode java lainnya.

Ingo
sumber
2

Ya, segala macam hal adalah mungkin. Dimungkinkan untuk melakukan pemrograman berorientasi objek dalam C; itu bukan ide yang bagus.

Java tidak dirancang untuk FP, jadi jika Anda mencoba melakukan semuanya dengan gaya FP murni, Anda akan mengalami masalah. Anda akan berjuang melawan bahasa, alih-alih bekerja dengannya. Dan tidak hanya bahasa - ada juga semua perpustakaan Java gratis yang indah. Jadi jangan menggunakan FP murni; ambil beberapa ide di balik FP dan mengintegrasikannya ke dalam kode Java Anda, tetapi pahamilah bahwa Anda tidak dapat melakukan itu untuk semua ide.

Mike Baranczak
sumber
0

Anda didorong oleh tim OpenJDK untuk mengunduh binari OpenJDK 8 terbaru dan bermain-main dengan ekspresi lambda baru dan idiom fungsional baru yang diperkenalkan di Collections API (antara lain). Anda dapat memprogram dengan gaya fungsional yang jelas. Lihat "Pemrograman fungsional di Jawa?" untuk perbandingan Koleksi JDK8 dengan lib Java8 pra seperti Guava, FunctionalJava dan LambdaJ.

JohanN
sumber
-3

Ini mungkin tampak mungkin tetapi itu tidak akan menjadi pemrograman fungsional murni. Mungkin menghasilkan pemrograman imperatif.

Tidak ada yang bertanya mengapa dia maksud dengan pemrograman fungsional yang mungkin seperti yang disebutkan oleh haylem. Ini dia:

Itu tergantung apa yang Anda maksud dengan "pemrograman fungsional" dan "mungkin".

Pemrograman fungsional tidak dapat memiliki definisi atau makna yang berbeda walaupun mungkin memiliki banyak penjelasan.
Seperti OOP, dapatkah kita bertanya "apa yang Anda maksud dengan OOP?".
Pasti akan ada banyak penjelasan tetapi hanya akan berkaitan dengan satu tujuan, yaitu tujuan OOP.
Hal yang sama berlaku untuk pemrograman fungsional .

Ketika kami mengatakan makna fungsional, program terdiri dari fungsi.
Peran fungsi adalah untuk mengembalikan argumen / parameter yang dievaluasi (argumen adalah variabel adalah ekspresi yang datang saat memanggil fungsi sementara parameter adalah variabel yang merupakan bagian dari deklarasi fungsi).

Juga fungsi akan selalu mengembalikan hasil yang sama ketika argumen yang sama dilewatkan. Dengan cara itu lebih mudah untuk menghindari bug atau men-debug bug masa depan. Dengan pemrograman fungsional kita dapat menghindari efek samping seperti memodifikasi variabel global.

contoh dalam JavaScript:

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

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

Peningkatan fungsi menambahkan 1 nilai ke setiap elemen di dalam objek dan mengembalikan hasilnya. Nilai myList tidak berubah tetapi ketika kita memanggil fungsi kita melihat nilai tambah untuk elemen objek itu.

Sebagai tanggapan saya terhadap Apakah Pemrograman Fungsional dimungkinkan di Jawa? , Saya percaya bahwa tidak mungkin untuk memiliki pemrograman fungsional yang benar di java. Karena java benar-benar dirancang untuk menjadi OOP di mana ia memperluas pemrograman imperatif dan memperbaikinya untuk pemeliharaan. Ketika keadaan objek, variabel dll, telah berubah, itu sudah merupakan pemrograman imperatif.

L34Rn3R
sumber