Apa keuntungan dan kerugian dari pendekatan C #, Java dan Scala to Closures / Lambdas /…?

30

Saya bertanya-tanya apa perbedaan implementasi teknis antara C # dan Scala dan bagaimana kedua solusi dibandingkan dengan ide-ide dan keprihatinan implementasi yang disuarakan dalam email Peek Past lambda oleh Brian Goetz, dikirim ke milis Project Lambda (JSR 335) ?

Dari email:

Kami menjelajahi jalan "mungkin lambdas hanya menjadi contoh kelas dalam, itu akan sangat sederhana", tetapi akhirnya sampai pada posisi "fungsi adalah arah yang lebih baik untuk masa depan bahasa".

dan selanjutnya:

Pandangan lambdas-adalah-objek tentang konflik dunia dengan masa depan yang memungkinkan ini. Pandangan lambda-fungsi-dunia tidak, dan menjaga fleksibilitas ini adalah salah satu poin yang mendukung tidak membebani lambda bahkan dengan penampilan objek-ness.

Kesimpulan:

Lambdas-are-functions membuka pintu. Lambdas-are-objek menutupnya.
Kami lebih suka melihat pintu-pintu itu dibiarkan terbuka.

Dan beberapa komentar dari seseorang di utas Reddit mengatakan:

Saya sebenarnya mengirim e-mail kepada Neal Gafter tentang ini dan untuk pemahaman saya yang terbatas tentang penjelasannya C # dan desain Java saat ini sangat mirip karena Delegasi sebenarnya objek dan bukan tipe fungsi. Sepertinya dia percaya bahwa Jawa harus belajar dari kerugian lambda C # dan menghindarinya (seperti halnya C # belajar dari kerugian Jawa dan menghindarinya pada awalnya).

Mengapa pendekatan "Lambdas-is-functions" memungkinkan lebih banyak peluang di masa depan daripada "Lambdas-are-objects"? Dapatkah seseorang menjelaskan perbedaan apa yang ada dan bagaimana mereka akan mempengaruhi bagaimana kode akan ditulis?

Melihat hal-hal di Scala "hanya bekerja", saya terus berpikir bahwa saya kehilangan sesuatu tentang pendekatan yang diambil / diusulkan dalam C # / Java (8), mungkin itu terkait dengan kekhawatiran tentang kompatibilitas mundur?

soc
sumber
1
Ini menarik. Mengingat bahwa sistem tipe Javas tidak memiliki konsep fungsi seperti sekarang, ini berarti seseorang harus memperkenalkan ini terlebih dahulu. Mungkin saja bahasanya menjadi terlalu rumit dengan ini.
Ingo
Bukankah fungsi seharusnya merupakan contoh dari beberapa antarmuka? Apa yang istimewa dari mereka?
soc
Lisp / Scheme / Clojure dapat memodelkan objek sementara Java / C # tidak dapat memodelkan fungsi fungsi yang berubah-ubah. Namun, Python tampaknya memiliki yang terbaik dari kedua dunia.
Pekerjaan

Jawaban:

15

Saya pikir diskusi tentang objek vs fungsi adalah herring merah. Jika pertanyaannya adalah, "Apakah lambda fungsi atau objek?" jawabannya harus ya .

Itulah inti dari fungsi kelas satu: mereka tidak diperlakukan berbeda dari tipe lainnya. Java sudah berhasil mengabaikan sebagian besar perbedaan antara Objek dan tipe primitif (dan Scala bahkan lebih baik), jadi apakah lambda adalah subkelas Objek atau tipe primitif baru atau sesuatu yang lain tidak terlalu penting untuk bahasa. Yang penting adalah bahwa Anda dapat menempatkan lambda Anda di koleksi, menyebarkannya untuk dipanggil, memanggil mereka, dan melakukan hal lain yang mungkin ingin Anda lakukan dengan objek atau metode.

Scala menyelesaikan ini dengan menggunakan objek wrapper yang memiliki metode yang disebut applyyang dapat dipanggil dengan adil (), membuatnya terlihat seperti pemanggilan metode. Ini bekerja dengan sangat baik; sebagian besar waktu Anda tidak perlu peduli apakah Anda memiliki metode atau memanggil objek fungsi.

Rex Kerr
sumber
9

Dari apa yang saya mengerti, ini lebih tentang bagaimana lambda dianggap pada tingkat bahasa utama. Seperti yang dikatakan dalam email,

Anda mungkin berpikir bahwa desain saat ini terikat erat pada kotak objek untuk jenis lambdas - SAM - menjadikannya objek yang efektif. Tapi ini telah disembunyikan dengan hati-hati dari permukaan sehingga memungkinkan kita untuk mempertimbangkan lambda 'telanjang' di masa depan, atau mempertimbangkan konteks konversi lain untuk lambda, atau mengintegrasikan lambda lebih erat ke konstruksi kontrol. Kami tidak melakukan itu sekarang, dan kami bahkan tidak memiliki rencana konkret untuk melakukannya, tetapi kemampuan untuk melakukan itu di masa depan adalah bagian penting dari desain.

Saya pikir itu meringkas pertanyaan Anda dengan cukup baik. Jika Anda menyatakan bahwa "lambdas adalah objek", maka mereka hanya objek dari kelas tertentu dan Anda terjebak dengan itu. Di sisi lain, jika Anda menyatakan "lambdas adalah fungsi", maka secara semantik Anda memiliki lapangan bermain yang lebih kaya. Java 1.7 mungkin mengkompilasinya ke objek, jadi mereka praktis identik pada saat itu.

Tetapi Java 1.8, atau 1.9, mungkin membawa perubahan pada bahasa (seperti jenis struktur yang direvisi) daripada memungkinkan fungsi untuk digunakan dengan cara yang jauh lebih fleksibel. Jika "lambdas adalah objek", perubahan ini tidak akan kompatibel dan Anda harus memperkenalkan konsep baru altogther, agar tidak merusak kode orang yang ada. Tetapi jika javachanya diam-diam mengubah lambdas menjadi objek di belakang layar, yang baru javacdapat mengubahnya menjadi apa pun yang diinginkan, selama semantik masih berlaku.

Andrzej Doyle
sumber
lamdas di C #! = dari delegasi. Kompiler memiliki opsi untuk mengkompilasinya ke delgate atau pohon Ekspresi. keduanya memang objek grafik tetapi mereka tidak dikompilasi untuk sebuah "kelas tertentu" atau bahkan kelas dari pohon warisan tertentu
Rune FS
Jika saya mengerti dengan benar, maka kompilasi lambda ke dalam kelas bagian dalam objek yang terkait dengan ikatan itu ke objek itu, jadi di masa depan jika Jawa akan memperkenalkan fungsi tingkat tinggi (fungsi pada tingkat objek yang sama) maka Anda tidak bisa menggunakan implementasi kelas dalam, dan akan ada ketidakkonsistenan. Saya tidak berpikir Java akan memiliki fungsi tingkat tinggi dalam waktu dekat.
mwolfetech
@ mwolfetech: Sejauh yang saya tahu, mereka sudah direncanakan untuk Java 8 dengan metode bek. Mereka ingin menambahkan hal-hal seperti foreach, map, filteruntuk koleksi.
soc
@soc Poin bagus, sulit untuk mengimbangi jumlah JSR dan apakah mereka benar-benar akan menyelesaikan dan membuat versi target JDK. Sepertinya metode bek mungkin menjadi bagian dari JSR yang sama. Berkenaan dengan JSR ini , saya menemukan bahwa postingan State of the Lambda karya Brian Goetz bermanfaat - menjelaskan tipe SAM dan pemikiran saat ini untuk menerapkan ekspresi lambda.
mwolfetech
"pemikiran saat ini" mhhh, bukankah postingan itu dari 2010 sudah usang sekarang?
soc
5

Kebanyakan, dia hanya tidak ingin melakukan terlalu cepat untuk sesuatu. Saya tidak melihat alasan di luar penghapus yang ia presentasikan, tapi itu memang alasan yang sangat kuat.

Saya tidak suka tipe fungsi - Saya suka tipe fungsi - tapi tipe fungsi itu bertarung dengan buruk dengan aspek yang ada pada sistem tipe Java, penghapusan. Tipe fungsi yang dihapus adalah yang terburuk dari kedua dunia.

Pertimbangkan metode ini dalam Scala's Regex:

def replaceAllIn (target: CharSequence, replacer: (Match)  String): String
def replaceSomeIn (target: CharSequence, replacer: (Match)  Option[String]): String

Akan lebih mudah jika mereka hanya ini:

def replace (target: CharSequence, replacer: (Match)  String): String
def replace (target: CharSequence, replacer: (Match)  Option[String]): String

Sayangnya, itu tidak mungkin, karena kedua fungsi tersebut identik di bawah penghapusan. Tapi, baiklah, fungsi ini melakukan hal yang agak berbeda, jadi nama yang berbeda mungkin cukup adil.

Namun, a Matchadalah sesuatu yang sangat berguna, tetapi sebagian besar waktu Anda ingin yang cocok Stringatau daftar subkelompok. Kami ingin memiliki ini:

def replaceAllIn (target: CharSequence, replacer: (String)  String): String
def replaceAllIn (target: CharSequence, replacer: (Seq[String])  String): String
def replaceAllIn (target: CharSequence, replacer: (Match)  String): String

Tidak mungkin, karena penghapusan. Saya memilih contoh khusus ini karena saya terlibat langsung dengannya, tetapi saya telah melihat setidaknya setengah lusin pertanyaan tentang Stack Overflow, di mana orang-orang bertanya mengapa kelebihan muatan itu ilegal, disebabkan oleh masalah persis ini.

Dan, kemudian, pertimbangkan bahwa pencocokan pola Scala dan Java instanceofsecara efektif tidak berguna karena penghapusan.

Saya pikir adil untuk menunda jenis fungsi sampai masalah ini ditangani. Lagi pula, ada banyak bahasa yang memilikinya di JVM, dan tidak seperti Java adalah bahasa yang berkembang dengan cepat.

Daniel C. Sobral
sumber
Nah, jika penghapusan tipe adalah satu-satunya masalah yang mereka miliki, apa yang mereka rencanakan? Melanggar setiap kode di planet ini sudah dianggap sebagai non-opsi untuk Java 5 ...
soc
@oc Saya sangat senang saya tidak di posisi mereka! Tapi itu Sun, ini Oracle. Oracle tidak pernah memiliki kesalahan dalam membuat perubahan antara versi utama - dan bahkan minor - produk utamanya.
Daniel C. Sobral
Mungkin mereka harus mengubah nama bahasa dan mulai mengembangkan bahasa baru, menjatuhkan kompatibilitas ke belakang. Jadi orang akan mendapat manfaat dari bahasa baru tanpa perlu bermain-main dengan bahasa yang lebih tua dan mapan. Lagipula, inilah yang dilakukan Scala dan Clojure.
Giorgio
@Iorgio Itu akan sedikit sia-sia. Ya, beberapa orang yang bertanggung jawab atas apa yang ada di Jawa saat ini melakukan hal itu, tetapi, seperti yang Anda katakan, ada beberapa alternatif. Tetapi orang-orang yang bertanggung jawab untuk Jawa harus memperbaiki Jawa itu sendiri - mereka bertanggung jawab untuk itu. Satu-satunya alternatif adalah dengan hanya menjatuhkan Java, dan melepaskan semua manfaat yang dihasilkan dari mengendalikannya.
Daniel C. Sobral
@Daniel C. Sobral: IMO bahasa pemrograman sedikit seperti perangkat lunak: pada awalnya itu bisa bersih dan dirancang dengan baik tetapi semakin Anda bermain dengannya semakin berantakan. Jadi saya pikir akan menjadi kepentingan pengembang untuk membekukan Java sebagai bahasa dan memusatkan pengembangan pada (1) membuat perpustakaan baru atau memperbaiki yang sudah ada, (2) meningkatkan JVM (jika mungkin), (3) mengembangkan bahasa baru . Tetapi seperti yang Anda katakan ada orang-orang yang bertanggung jawab untuk Java dan yang ingin terus menjual upgrade. Jadi mereka akan memperpanjangnya agar tetap "dingin". Hanya 2 sen saya.
Giorgio