Apakah memiliki variabel lokal yang dapat berubah dalam fungsi yang hanya digunakan secara internal, (misalnya fungsi tidak memiliki efek samping, setidaknya tidak sengaja) masih dianggap "tidak berfungsi"?
misalnya dalam pemeriksaan gaya program "Pemrograman fungsional dengan Scala" menganggap var
penggunaan apa pun sebagai buruk
Pertanyaan saya, jika fungsi tidak memiliki efek samping, apakah menulis kode gaya imperatif masih berkecil hati?
misal daripada menggunakan rekursi ekor dengan pola akumulator, apa yang salah dengan melakukan local untuk loop dan membuat mutable lokalListBuffer
dan menambahkannya, selama input tidak berubah?
Jika jawabannya "ya, mereka selalu berkecil hati, bahkan jika tidak ada efek samping" lalu apa alasannya?
functional-programming
Eran Medan
sumber
sumber
var
selalu tidak berfungsi. Scala memiliki optimasi malas dan rekursi ekor, yang memungkinkan untuk menghindari vars sepenuhnya.Jawaban:
Satu hal yang benar-benar praktik buruk di sini adalah mengklaim bahwa sesuatu adalah fungsi murni padahal sebenarnya tidak.
Jika variabel yang dapat diubah digunakan dengan cara yang benar-benar dan sepenuhnya mandiri, fungsinya secara eksternal murni dan semua orang senang. Haskell sebenarnya mendukung ini secara eksplisit , dengan sistem tipe yang bahkan memastikan bahwa referensi yang dapat diubah tidak dapat digunakan di luar fungsi yang membuatnya.
Yang mengatakan, saya pikir berbicara tentang "efek samping" bukan cara terbaik untuk melihatnya (dan itulah sebabnya saya mengatakan "murni" di atas). Apa pun yang menciptakan ketergantungan antara fungsi dan kondisi eksternal membuat hal-hal lebih sulit untuk dipikirkan, dan itu termasuk hal-hal seperti mengetahui waktu saat ini atau menggunakan keadaan yang dapat diubah yang tersembunyi dengan cara yang tidak aman.
sumber
Masalahnya bukan kemampuan berubah-ubah, itu adalah kurangnya transparansi referensial.
Suatu hal yang transparan referensial dan referensi padanya harus selalu sama, sehingga fungsi transparan referensial akan selalu mengembalikan hasil yang sama untuk set input yang diberikan dan "variabel" yang direferensikan transparan benar-benar nilai daripada variabel, karena itu tidak bisa berubah. Anda dapat membuat fungsi transparan referensial yang memiliki variabel yang bisa berubah di dalamnya; itu bukan masalah. Namun, mungkin lebih sulit untuk memastikan fungsi tersebut transparan secara referensi, tergantung pada apa yang Anda lakukan.
Ada satu contoh yang bisa saya pikirkan di mana kemampuan harus digunakan untuk melakukan sesuatu yang sangat fungsional: memoisasi. Memoisasi adalah caching nilai dari suatu fungsi, sehingga tidak harus dihitung ulang; itu transparan referensial, tetapi menggunakan mutasi.
Tetapi dalam transparansi referensial umum dan immutabilitas berjalan bersama, selain variabel lokal yang bisa berubah dalam fungsi transparan dan memoisasi referensial, saya tidak yakin ada contoh lain di mana hal ini tidak terjadi.
sumber
Tidak baik untuk merebusnya menjadi "praktik yang baik" vs "praktik yang buruk". Scala mendukung nilai-nilai yang bisa berubah karena mereka memecahkan masalah-masalah tertentu jauh lebih baik daripada nilai-nilai yang tidak berubah, yaitu mereka yang sifatnya berulang.
Untuk perspektif, saya cukup yakin bahwa melalui
CanBuildFrom
hampir semua struktur abadi yang disediakan oleh scala lakukan semacam mutasi secara internal. Intinya adalah bahwa apa yang mereka ungkapkan tidak berubah. Menjaga sebanyak mungkin nilai yang tidak berubah mungkin membantu membuat program lebih mudah untuk dipikirkan dan lebih sedikit rawan kesalahan .Ini tidak berarti bahwa Anda perlu menghindari struktur dan nilai yang bisa berubah secara internal ketika Anda memiliki masalah yang lebih cocok dengan kemampuan berubah-ubah.
Dengan mengingat hal itu, banyak masalah yang biasanya memerlukan variabel yang dapat berubah (seperti perulangan) dapat diselesaikan dengan lebih baik dengan banyak fungsi tingkat tinggi yang disediakan oleh bahasa seperti Scala (peta / filter / lipat). Sadarilah itu.
sumber
map
,filter
,foldLeft
DanforEach
melakukan trik sebagian besar waktu, tetapi ketika mereka tidak, bisa merasa saya "OK" untuk kembali kepada kekerasan kode penting bagus. (selama tidak ada efek samping tentunya)Selain kemungkinan masalah dengan keselamatan ulir, Anda juga biasanya kehilangan banyak jenis pengaman. Loop imperatif memiliki tipe pengembalian
Unit
dan dapat mengambil cukup banyak ekspresi untuk input. Fungsi tingkat tinggi dan bahkan rekursi memiliki semantik dan tipe yang jauh lebih presisi.Anda juga memiliki lebih banyak opsi untuk pemrosesan kontainer fungsional dibandingkan dengan loop imperatif. Dengan penting, pada dasarnya anda memiliki
for
,while
, dan variasi kecil pada kedua sepertido...while
danforeach
.Secara fungsional, Anda memiliki agregat, menghitung, memfilter, menemukan, flatMap, lipat, groupBy, lastIndexWhere, map, maxBy, minBy, partisi, scan, sortBy, sortWith, span, dan takeWhile, hanya untuk menyebutkan beberapa yang lebih umum dari Scala's perpustakaan standar. Ketika Anda terbiasa memiliki yang tersedia,
for
loop imperatif tampak terlalu mendasar dibandingkan.Satu-satunya alasan nyata untuk menggunakan mutabilitas lokal adalah sangat sesekali untuk kinerja.
sumber
Saya akan mengatakan itu sebagian besar ok. Terlebih lagi, membuat struktur dengan cara ini mungkin merupakan cara yang baik untuk meningkatkan kinerja dalam beberapa kasus. Clojure telah mengatasi masalah ini dengan menyediakan struktur data Transient .
Ide dasarnya adalah untuk memungkinkan mutasi lokal dalam lingkup terbatas, dan kemudian membekukan struktur sebelum mengembalikannya. Dengan cara ini, pengguna Anda masih dapat alasan tentang kode Anda seolah-olah itu murni, tetapi Anda dapat melakukan transformasi tempat ketika Anda perlu.
Seperti yang dikatakan tautan:
sumber
Tidak memiliki variabel yang dapat berubah lokal memang memiliki satu keunggulan - itu membuat fungsi lebih ramah terhadap utas.
Saya terbakar oleh variabel lokal seperti itu (tidak dalam kode saya, juga tidak memiliki sumber) yang menyebabkan korupsi data probabilitas rendah. Keamanan utas tidak disebutkan satu atau lain cara, tidak ada keadaan yang bertahan di seluruh panggilan dan tidak ada efek samping. Tidak terpikir oleh saya bahwa itu mungkin bukan thread yang aman, mengejar 1 dalam 100.000 data acak korupsi adalah rasa sakit kerajaan.
sumber