Banyak bahasa pemrograman modern mendukung beberapa konsep penutupan , yaitu sepotong kode (blok atau fungsi) itu
- Dapat diperlakukan sebagai nilai, dan karena itu disimpan dalam variabel, diedarkan ke berbagai bagian kode, didefinisikan dalam satu bagian dari program dan dipanggil dalam bagian yang sama sekali berbeda dari program yang sama.
- Dapat menangkap variabel dari konteks di mana ia didefinisikan, dan mengaksesnya ketika nanti dipanggil (mungkin dalam konteks yang sama sekali berbeda).
Berikut adalah contoh penutupan yang ditulis dalam Scala:
def filterList(xs: List[Int], lowerBound: Int): List[Int] =
xs.filter(x => x >= lowerBound)
Fungsi literal x => x >= lowerBound
berisi variabel bebas lowerBound
, yang ditutup (terikat) oleh argumen fungsi filterList
yang memiliki nama yang sama. Penutupan diteruskan ke metode perpustakaan filter
, yang dapat memanggilnya berulang kali sebagai fungsi normal.
Saya telah membaca banyak pertanyaan dan jawaban di situs ini dan, sejauh yang saya mengerti, istilah penutupan sering secara otomatis dikaitkan dengan pemrograman fungsional dan gaya pemrograman fungsional.
Definisi pemrograman fungsi pada wikipedia berbunyi:
Dalam ilmu komputer, pemrograman fungsional adalah paradigma pemrograman yang memperlakukan komputasi sebagai evaluasi fungsi matematika dan menghindari keadaan dan data yang bisa berubah. Ini menekankan penerapan fungsi, berbeda dengan gaya pemrograman imperatif, yang menekankan perubahan dalam keadaan.
dan selanjutnya
[...] dalam kode fungsional, nilai output suatu fungsi hanya bergantung pada argumen yang diinput ke fungsi [...]. Menghilangkan efek samping dapat membuatnya lebih mudah untuk memahami dan memprediksi perilaku suatu program, yang merupakan salah satu motivasi utama untuk pengembangan pemrograman fungsional.
Di sisi lain, banyak konstruksi penutupan yang disediakan oleh bahasa pemrograman memungkinkan penutupan untuk menangkap variabel non-lokal dan mengubahnya ketika penutupan itu dipanggil, sehingga menghasilkan efek samping pada lingkungan di mana mereka didefinisikan.
Dalam hal ini, closure mengimplementasikan ide pertama pemrograman fungsional (fungsi adalah entitas kelas satu yang dapat digerakkan seperti nilai-nilai lainnya) tetapi mengabaikan ide kedua (menghindari efek samping).
Apakah penggunaan penutupan dengan efek samping ini dianggap sebagai gaya fungsional atau apakah penutupan dianggap sebagai konstruksi yang lebih umum yang dapat digunakan baik untuk gaya pemrograman fungsional maupun non-fungsional? Apakah ada literatur tentang topik ini?
CATATAN PENTING
Saya tidak mempertanyakan kegunaan efek samping atau memiliki penutupan dengan efek samping. Juga, saya tidak tertarik dalam diskusi tentang keuntungan / kerugian penutupan dengan atau tanpa efek samping.
Saya hanya tertarik untuk mengetahui apakah menggunakan penutupan seperti itu masih dianggap gaya fungsional oleh pendukung pemrograman fungsional atau jika, sebaliknya, penggunaannya tidak disarankan ketika menggunakan gaya fungsional.
sumber
Jawaban:
Tidak; definisi paradigma fungsional adalah tentang kurangnya keadaan dan secara implisit kurangnya efek samping. Ini bukan tentang fungsi tingkat tinggi, penutupan, manipulasi daftar yang didukung bahasa atau fitur bahasa lainnya ...
Nama pemrograman fungsional berasal dari pengertian matematika tentang fungsi - panggilan berulang pada input yang sama selalu memberikan output yang sama - fungsi nullipotent. Ini hanya dapat dicapai jika data tidak dapat diubah . Untuk memudahkan pengembangan, fungsi-fungsi menjadi bisa berubah (fungsi berubah, data masih tidak berubah) dan dengan demikian pengertian fungsi tingkat tinggi (fungsional dalam matematika, sebagai turunan misalnya) - fungsi yang mengambil input fungsi lain. Untuk kemungkinan fungsi untuk dibawa-bawa dan diteruskan sebagai argumen, fungsi kelas satu diadopsi; mengikuti ini, untuk lebih meningkatkan produktivitas, penutupan muncul.
Ini, tentu saja, pandangan yang sangat sederhana.
sumber
map
, misalnya, yang mengambil fungsi, menerapkannya ke daftar, dan mengembalikan daftar hasil.map
tidak mengubah salah satu argumennya, itu tidak mengubah perilaku fungsi yang dibutuhkan sebagai argumen, tetapi jelas merupakan fungsi tingkat tinggi - jika Anda menerapkannya sebagian, hanya dengan parameter fungsi, Anda telah membangun sebuah fungsi baru yang beroperasi pada daftar, tetapi masih belum terjadi mutasi.Tidak. "Fungsional-gaya" menyiratkan pemrograman bebas efek samping.
Untuk mengetahui alasannya, lihat entri blog Eric Lippert tentang
ForEach<T>
metode ekstensi, dan mengapa Microsoft tidak menyertakan metode urutan seperti itu di Linq :sumber
ParallelQuery<T>.ForAll(...)
. Implementasi sepertiIEnumerable<T>.ForEach(...)
itu sangat berguna untuk men -debugForAll
pernyataan (gantiForAll
denganForEach
dan hapusAsParallel()
dan Anda bisa lebih mudah melangkah / debug itu)Pemrograman fungsional membawa fungsi kelas satu ke tingkat konseptual berikutnya, tetapi mendeklarasikan fungsi anonim atau meneruskan fungsi ke fungsi lain tidak selalu merupakan hal pemrograman fungsional. Di C, semuanya bilangan bulat. Sejumlah, penunjuk ke data, penunjuk ke fungsi ... semua hanya int. Anda bisa meneruskan pointer fungsi ke fungsi lain, membuat daftar pointer fungsi ... Heck, jika Anda bekerja dalam bahasa assembly, fungsi sebenarnya hanya alamat di memori tempat blok instruksi mesin disimpan. Memberi fungsi nama adalah overhead tambahan bagi orang-orang yang membutuhkan kompiler untuk menulis kode. Jadi fungsi adalah "kelas satu" dalam arti dalam bahasa yang sama sekali tidak berfungsi.
Jika satu-satunya hal yang Anda lakukan adalah menghitung rumus matematika dalam REPL, maka Anda dapat secara fungsional murni dengan bahasa Anda. Tetapi kebanyakan pemrograman bisnis memiliki efek samping. Kehilangan uang sambil menunggu program jangka panjang selesai adalah efek sampingnya. Mengambil tindakan eksternal apa pun: menulis ke file, memperbarui basis data, mencatat aktivitas secara berurutan, dll. Memerlukan perubahan status. Kami dapat memperdebatkan apakah keadaan benar-benar berubah jika Anda merangkum tindakan ini dalam pembungkus abadi yang mendorong efek samping sehingga kode Anda tidak perlu khawatir tentang hal itu. Tapi itu seperti mendiskusikan apakah pohon mengeluarkan suara jika jatuh di hutan tanpa ada yang mendengarnya. Faktanya adalah bahwa pohon itu mulai tegak dan berakhir di tanah. Status berubah ketika hal-hal dilakukan, bahkan jika hanya melaporkan bahwa hal-hal itu dilakukan.
Jadi kita dibiarkan dengan skala kemurnian fungsional, bukan hitam dan putih, tetapi nuansa abu-abu. Dan pada skala itu, semakin sedikit efek samping, semakin sedikit sifat berubah-ubah, semakin baik (lebih fungsional).
Jika Anda benar-benar memerlukan efek samping atau keadaan yang dapat berubah dalam kode fungsional Anda, Anda berusaha untuk merangkum atau membuatnya dari sisa program Anda sebaik mungkin. Menggunakan penutupan (atau apa pun) untuk menyuntikkan efek samping atau keadaan bisa berubah menjadi fungsi murni sebaliknya adalah kebalikan dari pemrograman fungsional. Satu-satunya pengecualian mungkin jika penutupan adalah cara paling efektif untuk merangkum efek samping dari kode yang diteruskan. Ini masih bukan "pemrograman fungsional" tetapi mungkin lemari yang bisa Anda dapatkan dalam situasi tertentu.
sumber