Karena kemurnian parameter input tidak diketahui hingga runtime, apakah fungsi segera dianggap tidak murni jika mengambil fungsi sebagai parameter input?
Terkait: jika suatu fungsi menerapkan fungsi murni yang didefinisikan di luar fungsi, tetapi tidak dimasukkan sebagai parameter, apakah masih murni jika memenuhi kriteria tidak memiliki efek samping dan output hanya bergantung pada input?
Untuk konteks, saya sedang menulis kode fungsional dalam JavaScript.
functional-programming
pure-function
Dancrumb
sumber
sumber
foo = function(function bar){ print(bar.toString()) }
foo = function(function bar) { return 3; }
adalah murni, dan mengambil fungsi sebagai argumen.toString()
(yaitu yang Anda akan temukan di Obyek Java).Jawaban:
Selama semua nilai yang digunakan dalam fungsi ditentukan hanya oleh parameternya, itu adalah fungsi murni.
Faset yang outputnya sama setiap kali untuk input yang sama dikendalikan oleh apakah parameternya murni. Jika Anda menganggap parameter (seperti argumen fungsi) juga murni, maka itu murni.
Dalam bahasa seperti Javascript di mana kemurnian tidak ditegakkan, ini berarti bahwa dimungkinkan untuk membuat fungsi yang murni memiliki perilaku tidak murni dengan menjalankan fungsi tidak murni yang dilewatkan sebagai parameter.
Ini secara efektif berarti bahwa untuk bahasa yang tidak menegakkan kemurnian (yaitu hampir semua), tidak mungkin untuk mendefinisikan fungsi murni yang memanggil fungsi yang dilewatkan sebagai argumen. Masih berguna untuk menulisnya semurni mungkin, dan untuk menanggapinya sebagai fungsi murni, tetapi Anda harus berhati-hati karena asumsi bahwa itu murni akan rusak jika Anda memberikan argumen yang salah.
Dalam pengalaman saya dalam praktik, ini biasanya bukan masalah besar - saya merasa jarang memiliki fungsi yang tidak murni digunakan sebagai argumen fungsi untuk fungsi murni.
sumber
areaOfCircle r => Math.Pi * r * r
, apakah akanareaOfCircle
non-murni karena tidak hanya menggunakan parameter?f(f2)
bahwa fungsi yang dipanggilf2
tidak bergantung secara transitif pada apa pun yangf2
diandalkan. Fungsi yang mungkin menjalankan fungsi sewenang-wenang tidak murni.function compose(f, g) {return function h(x) {return f(g(x));};}
, yang murni meskipun mengambil fungsi sebagai argumen.find
rutin predikat tidak murni yang mengembalikan "benar" untuk item pencocokan ketiga yang dijumpainya, atau omong kosong semacam itu.Tidak. Contoh balik:
Tidak masalah apakah
other_function
itu fungsi murni, fungsi tidak murni, atau tidak fungsi sama sekali. Thepure
fungsi murni.Contoh tandingan lainnya:
Fungsi ini murni, meskipun
x
merupakan fungsi yang tidak murni.identity(impure_function)
akan selalu kembaliimpure_function
, tidak peduli berapa kali Anda mengulangi panggilan. Tidak masalah apakahidentity(impure_function)()
selalu mengembalikan hal yang sama; nilai pengembalian nilai fungsi tidak mempengaruhi kemurniannya.Secara umum, jika suatu fungsi mungkin memanggil fungsi itu disahkan sebagai argumen, itu tidak murni. Misalnya, suatu fungsi
function call(f) {f();}
tidak murni, karena meskipun tidak menyebutkan keadaan global atau yang bisa berubah,f
mungkin sesuatu sepertialert
itu yang menyebabkan efek samping yang terlihat.Jika suatu fungsi mengambil fungsi sebagai argumen, tetapi tidak memanggilnya atau menyebabkannya dipanggil, maka itu bisa murni. Mungkin masih tidak murni jika melakukan beberapa hal tidak murni lainnya. Misalnya,
function f(ignored_function) {alert('This isn't pure.');}
tidak murni, meskipun tidak pernah memanggilignored_function
.sumber
Secara teknis, ya, kecuali ada beberapa cara dalam bahasa Anda untuk menjamin bahwa fungsi input juga murni.
Iya. Jadi mari kita fokus pada apa yang penting di sini. Memanggil fungsi murni atau tidak tidak berguna. Fungsi murni bermanfaat karena menghasilkan output yang sama untuk input apa pun dan tidak bergantung pada status atau memiliki efek samping adalah serangkaian properti yang sangat berguna. Ini berarti bahwa setelah fungsi Anda dijalankan, Anda dapat "mengingat" jawaban untuk input itu dan itu akan selalu benar. Anda juga tidak perlu menjalankan fungsi lagi untuk menghasilkan efek samping. Dan Anda dapat menjalankan fungsi itu secara paralel (atau rusak) dengan fungsi lain dan tahu bahwa mereka tidak akan memiliki interaksi tersembunyi yang berperilaku buruk.
Properti yang bermanfaat itu masih berlaku jika fungsi menggunakan fungsi read-only murni lainnya untuk melakukan tugasnya, terlepas dari bagaimana referensi itu.
sumber
Seperti yang dikatakan Telastyn: Secara teknis, ya, kecuali ada beberapa cara dalam bahasa Anda untuk menjamin bahwa fungsi input juga murni.
Itu bukan hipotesis, memang ada cara yang baik untuk menjamin ini. Setidaknya dalam bahasa yang sangat diketik.
Seperti fungsi ~ murni yang akan Anda tulis dalam JavaScript
dapat diterjemahkan langsung ke Haskell:
Sekarang, di JavaScript Anda bisa melakukan hal-hal jahat
Ini tidak mungkin di Haskell . Alasannya, sesuatu seperti efek samping
console.log()
harus selalu memiliki tipe hasilIO something
, tidak hanyasomething
sendirian.Untuk ekspresi ini untuk mengetik centang, kita perlu memberikan
foo
tanda tangan jenisTapi ternyata saya tidak bisa mengimplementasikannya lagi: karena fungsi argumen ada
IO
di hasilnya, saya tidak bisa menggunakannya di dalamnyafoo
.Satu-satunya cara saya bisa menggunakan
IO
tindakanfoo
adalah jika hasilfoo
memiliki tipeIO Int
itu sendiri:Tetapi pada titik ini jelas dari tanda tangan
foo
bahwa itu juga bukan fungsi murni.sumber
unsafeIO
:-)IO
. Kebetulan, itu juga dapat digunakan untuk menyebabkan kekacauan dengan menyembunyikan efek samping dalam fungsi "murni", tapi itu benar - benar tidak aman di Haskell karena tidak ada cara yang dapat diandalkan untuk menentukan urutan evaluasi fungsi murni.unsafeIO
; itu adalah jalan keluar penyelamatan terakhir yang menghindari jaminan tipe sistem, dan karenanya milik Anda bukanlah poin yang baik.Tidak, bukan itu.
Jika fungsi yang diteruskan tidak murni DAN fungsi Anda memanggil fungsi yang lewat maka fungsi Anda akan dianggap tidak murni.
Relasi murni / tidak murni agak mirip sinkronisasi / async di JS. Anda dapat dengan bebas menggunakan kode murni dari yang tidak murni, tetapi tidak sebaliknya.
sumber