Dalam bahasa pemrograman, penutupan adalah fitur yang populer dan sering diinginkan. Wikipedia mengatakan (beri penekanan pada saya):
Dalam ilmu komputer, closure (...) adalah fungsi bersama-sama dengan lingkungan referensi untuk variabel non-lokal dari fungsi itu. Penutupan memungkinkan suatu fungsi untuk mengakses variabel di luar lingkup leksikal langsungnya.
Jadi penutupan pada dasarnya adalah nilai fungsi (anonim?) Yang dapat menggunakan variabel di luar cakupannya sendiri. Dalam pengalaman saya, ini berarti dapat mengakses variabel yang ada dalam ruang lingkup pada titik definisi.
Dalam praktiknya, konsepnya tampaknya menyimpang, setidaknya di luar pemrograman fungsional. Bahasa yang berbeda menerapkan semantik yang berbeda, bahkan tampaknya ada perang pendapat. Banyak programmer tampaknya tidak tahu apa penutupan itu, melihat mereka sebagai lebih dari fungsi anonim.
Juga, tampaknya ada hambatan besar ketika menerapkan penutupan. Paling menonjol, Java 7 seharusnya menyertakan mereka tetapi fitur itu didorong kembali ke rilis masa depan.
Mengapa penutupan begitu sulit (untuk dipahami dan) untuk direalisasikan? Ini adalah pertanyaan yang terlalu luas dan tidak jelas, jadi izinkan saya lebih memfokuskannya dengan pertanyaan yang saling terkait ini:
- Apakah ada masalah dengan mengekspresikan penutupan dalam formalisme semantik yang umum (langkah kecil, langkah besar, ...)?
- Apakah sistem tipe yang ada tidak cocok untuk penutupan dan tidak dapat diperpanjang dengan mudah?
- Apakah bermasalah untuk membuat penutupan sejalan dengan terjemahan prosedur tradisional berbasis stack?
Perhatikan bahwa pertanyaan ini sebagian besar berkaitan dengan bahasa prosedural, berorientasi objek, dan skrip pada umumnya. Sejauh yang saya tahu, bahasa fungsional tidak memiliki masalah.
sumber
Jawaban:
Bolehkah saya mengarahkan Anda ke halaman wikipedia masalah Funarg ? Setidaknya begitulah orang-orang penyusun digunakan untuk referensi masalah implementasi penutupan.
Sementara definisi ini masuk akal, itu tidak membantu menggambarkan masalah penerapan fungsi kelas satu dalam bahasa tradisional runtime-stack. Ketika datang ke masalah implementasi, fungsi kelas satu dapat secara kasar dibagi menjadi dua kelas:
Kasus pertama (ke bawah funargs) tidak terlalu sulit untuk diimplementasikan dan dapat ditemukan bahkan pada bahasa prosedural yang lebih lama, seperti Algol, C dan Pascal. C jenis rok masalah, karena tidak memungkinkan fungsi bersarang tetapi Algol dan Pascal melakukan pembukuan yang diperlukan untuk memungkinkan fungsi dalam referensi variabel stack dari fungsi luar.
Kasus kedua (ke atas funargs), di sisi lain, membutuhkan catatan aktivasi untuk disimpan di luar tumpukan, di heap. Ini berarti sangat mudah untuk membocorkan sumber daya memori kecuali bahasa runtime termasuk pengumpul sampah. Sementara hampir semuanya adalah sampah yang dikumpulkan hari ini, membutuhkan satu masih keputusan desain yang signifikan dan bahkan lebih dari beberapa waktu lalu.
Adapun contoh khusus Jawa, jika saya ingat dengan benar, masalah utama sebenarnya tidak bisa menerapkan penutupan, tetapi bagaimana memperkenalkan mereka ke bahasa dengan cara yang tidak berlebihan dengan fitur yang ada (seperti kelas dalam anonim) dan yang tidak berbenturan dengan fitur yang ada (seperti pengecualian yang diperiksa - masalah yang bukan hal sepele yang harus saya pecahkan dan yang kebanyakan orang tidak pikirkan pada awalnya).
Saya juga dapat memikirkan hal-hal lain yang membuat fungsi kelas pertama kurang sepele untuk diimplementasikan, seperti memutuskan apa yang harus dilakukan dengan variabel "ajaib" seperti ini , mandiri atau super dan bagaimana berinteraksi dengan operator aliran kontrol yang ada, seperti istirahat dan kembali (apakah kami ingin mengizinkan pengembalian non-lokal atau tidak?). Tetapi pada akhirnya, popularitas fungsi kelas satu baru-baru ini tampaknya menunjukkan bahwa bahasa yang tidak memilikinya sebagian besar melakukannya karena alasan historis atau karena beberapa keputusan desain yang signifikan sejak awal.
sumber
ref
parameter"). Jika penelepon merangkum semua variabel yang menarik dalam struktur, delegasi bisa sepenuhnya statis, menghindari kebutuhan untuk alokasi tumpukan. Compiler tidak menawarkan bantuan sintaks yang bagus untuk konstruksi seperti itu, tetapi Kerangka dapat mendukung mereka.Kita bisa melihat bagaimana penutupan diimplementasikan dalam C #. Skala transformasi yang dilakukan oleh kompiler C # memperjelas bahwa cara mereka menerapkan penutupan cukup banyak pekerjaan. Mungkin ada cara yang lebih mudah untuk menerapkan penutupan, tapi saya pikir tim C # compiler akan mengetahui hal ini.
Pertimbangkan pseudo-C # berikut (saya hentikan beberapa hal spesifik C #):
Kompiler mengubah ini menjadi sesuatu seperti ini:
(pada kenyataannya, variabel f masih akan dibuat, di mana f adalah 'delegate' (= function pointer), tetapi delegate ini masih terkait dengan objek theClosureObject - saya meninggalkan bagian ini untuk kejelasan bagi mereka yang tidak terbiasa dengan C #)
Transformasi ini cukup besar dan rumit: pertimbangkan penutupan di dalam penutupan dan interaksi penutupan dengan sisa fitur bahasa C #. Saya bisa membayangkan bahwa fitur itu didorong kembali untuk Java, karena Java 7 sudah memiliki cukup banyak fitur baru.
sumber
Untuk menjawab bagian dari pertanyaan Anda. Formalisme yang dijelaskan oleh Morrisett dan Harper mencakup semantik langkah besar dan kecil dari bahasa polimorfik tingkat tinggi yang mengandung penutup. Ada makalah sebelum ini yang menyediakan jenis semantik yang Anda cari. Lihat, misalnya, di mesin SECD . Menambahkan referensi yang bisa berubah atau lokal yang bisa berubah ke semantik ini sangatlah mudah. Saya tidak melihat ada masalah teknis dalam menyediakan semantik seperti itu.
sumber