Saya telah mencoba memahami mengapa JDK 8 Lambda Expert Group (EG) memutuskan untuk tidak memasukkan jenis fungsi baru ke dalam bahasa pemrograman Java.
Menuju milis saya menemukan utas dengan diskusi tentang penghapusan jenis fungsi .
Banyak pernyataan yang ambigu bagi saya, mungkin karena kurangnya konteks dan dalam beberapa kasus karena pengetahuan saya yang terbatas tentang implementasi sistem tipe.
Namun, ada beberapa pertanyaan yang saya yakin dapat dirumuskan dengan aman di situs ini untuk membantu saya memahami dengan lebih baik apa artinya.
Saya tahu saya bisa mengajukan pertanyaan di milis, tetapi utasnya sudah tua dan semua keputusan sudah dibuat, jadi kemungkinan besar saya akan diabaikan, terutama melihat bahwa orang-orang ini sudah tertunda dengan rencana mereka.
Dalam jawabannya untuk mendukung penghapusan tipe fungsi dan mendukung penggunaan tipe SAM, Brian Goetz mengatakan:
Tidak ada reifikasi. Ada utas panjang tentang seberapa berguna bagi jenis fungsi untuk diverifikasi. Tanpa reifikasi, tipe-tipe fungsi tertatih-tatih.
Saya tidak dapat menemukan utas yang ia sebutkan. Sekarang, saya dapat memahami bahwa pengenalan tipe fungsi struktural mungkin menyiratkan komplikasi tertentu dalam sistem tipe kebanyakan Java, apa yang saya tidak bisa mengerti adalah bagaimana perbedaan tipe SAM berbeda dalam hal reifikasi.
Bukankah mereka berdua mengalami masalah reifikasi yang sama? Apakah ada yang mengerti bagaimana tipe fungsi berbeda dari tipe SAM yang diparameterisasi dalam hal reifikasi?
Dalam komentar lain Goetz mengatakan:
Ada dua pendekatan dasar untuk mengetik: nominal dan struktural. Identitas nominal didasarkan pada namanya; identitas tipe struktural didasarkan pada apa yang tersusun dari (seperti "tupel int, int" atau "fungsi dari int ke float".) Sebagian besar bahasa memilih sebagian besar nominal atau sebagian besar struktural; tidak ada banyak bahasa yang berhasil mencampur pengetikan nominal dan struktural kecuali "di tepinya." Java hampir seluruhnya nominal (dengan beberapa pengecualian: array adalah tipe struktural, tetapi di bagian bawah selalu ada tipe elemen nominal; generik memiliki campuran nominal dan struktural juga, dan ini sebenarnya merupakan bagian dari sumber banyak keluhan orang tentang obat generik.) Mencangkok sistem tipe struktural (tipe fungsi) ke Java ' Sistem tipe nominal berarti kompleksitas baru dan kasing tepi. Apakah manfaat tipe fungsi sepadan dengan ini?
Bagi Anda yang berpengalaman dalam implementasi sistem tipe. Apakah Anda tahu contoh kompleksitas atau kasus tepi yang ia sebutkan di sini?
Jujur saya bingung dengan tuduhan ini ketika saya menganggap bahwa bahasa pemrograman seperti Scala, yang sepenuhnya didasarkan pada JVM, memiliki dukungan untuk tipe struktural seperti fungsi dan tupel, bahkan dengan masalah reifikasi platform yang mendasarinya.
Jangan salah paham, saya tidak mengatakan bahwa tipe fungsi harus lebih baik daripada tipe SAM. Saya hanya ingin mengerti mengapa mereka mengambil keputusan ini.
sumber
Jawaban:
Pendekatan SAM sebenarnya agak mirip dengan apa yang Scala (dan C ++ 11) lakukan dengan fungsi anonim (dibuat dengan
=>
operator Scala atau[]()
sintaksis C ++ 11 (lambda)).Pertanyaan pertama yang harus dijawab di sisi Jawa adalah apakah memiliki tipe kembalinya dari pernyataan lambda menjadi tipe primitif baru, seperti
int
ataubyte
, atau tipe objek semacam itu. Dalam Scala, ada yang tidak ada tipe primitif - bahkan integer adalah obyek dari kelasInt
- dan fungsi yang tidak berbeda, menjadi objek dari kelasFunction1
,Function2
dan sebagainya, tergantung pada jumlah argumen fungsi mengambil.C ++ 11, ruby dan python juga memiliki ekspresi lambda yang mengembalikan objek yang dapat dipanggil secara eksplisit atau implisit. Objek yang dikembalikan memiliki beberapa metode standar (seperti
#call
yang dapat digunakan untuk memanggilnya sebagai fungsi. C ++ 11, misalnya, menggunakanstd::function
tipe yang kelebihanoperator()
sehingga panggilan metode panggilan objek bahkan terlihat seperti pemanggilan fungsi, secara tekstual. :-)Di mana proposal baru untuk Java menjadi berantakan adalah dalam penggunaan pengetikan struktural untuk memungkinkan menetapkan metode seperti itu ke objek lain, seperti
Comparator
yang memiliki metode utama tunggal dengan nama yang berbeda . Sementara ini secara konseptual idih dalam beberapa hal, itu tidak berarti bahwa objek yang dihasilkan dapat dikirimkan ke fungsi yang ada yang mengambil objek untuk mewakili callback, pembanding, dan seterusnya, dan berharap untuk dapat memanggil didefinisikan dengan baik tunggal metode seperti#compare
atau#callback
. Trik C ++ untuk mengesampingkan secaraoperator()
rapi menghindari masalah ini bahkan sebelum C ++ 11, karena semua opsi panggilan balik seperti itu dapat dipanggil dengan cara yang sama, dan dengan demikian STL tidak memerlukan penyesuaian untuk memungkinkan C ++ 11 lambdas digunakan dengansort
dan seterusnya. Java, tidak pernah menggunakan penamaan standar untuk objek seperti itu di masa lalu (mungkin karena tidak ada trik seperti overloading operator membuat pendekatan tunggal jelas), tidak begitu beruntung, jadi peretasan ini mencegah mereka dari harus mengubah banyak API yang ada .sumber
java.util.Function2<T1, T2, R>
di Java 1.0, maka tidak akan adaComparator
antarmuka, sebaliknya semua metode tersebut akan mengambilFunction2<T1, T2, int>
. (Ya, akan ada seluruh petak antarmuka sepertiFunction2TT_int<T1, T2>
karena primitif, tetapi Anda mengerti maksud saya.)