Apakah fungsi berikut murni?
function test(min,max) {
return Math.random() * (max - min) + min;
}
Pemahaman saya adalah bahwa fungsi murni mengikuti kondisi berikut:
- Ini mengembalikan nilai yang dihitung dari parameter
- Itu tidak melakukan pekerjaan apa pun selain menghitung nilai pengembalian
Jika definisi ini benar, apakah fungsi saya fungsi murni? Atau apakah pemahaman saya tentang apa yang mendefinisikan fungsi murni salah?
javascript
function
pure-function
Kiwi Rupela
sumber
sumber
Math.random()
yang mengubah status RNG.test(a,b)
selalu mengembalikan objek yang samaRandom(a,b)
(yang dapat mewakili bilangan beton yang berbeda)? Jika Anda menyimpanRandom
simbolik, itu murni dalam pengertian klasik, jika Anda mengevaluasinya lebih awal dan memasukkan angka, mungkin sebagai semacam pengoptimalan, fungsinya masih mempertahankan beberapa "kemurnian".Jawaban:
Tidak, tidak. Dengan input yang sama, fungsi ini akan mengembalikan nilai yang berbeda. Dan kemudian Anda tidak dapat membuat 'tabel' yang memetakan input dan output.
Dari artikel Wikipedia untuk fungsi Pure :
Juga, hal lain adalah bahwa fungsi murni dapat diganti dengan tabel yang mewakili pemetaan dari input dan output, seperti yang dijelaskan di thread ini .
Jika Anda ingin menulis ulang fungsi ini dan mengubahnya menjadi fungsi murni, Anda juga harus meneruskan nilai acak sebagai argumen
lalu menyebutnya seperti ini (contoh, dengan 2 dan 5 sebagai min dan max):
sumber
Math.random
?Math.random
hasil di masa mendatang ); agar menjadi murni, Anda harus entah bagaimana menyimpan status RNG saat ini, memasang kembali, memanggilMath.random
, dan memulihkannya ke status sebelumnya.Jawaban sederhana untuk pertanyaan Anda adalah yang
Math.random()
melanggar aturan # 2.Banyak jawaban lain di sini yang menunjukkan bahwa keberadaan
Math.random()
sarana fungsi ini tidak murni. Tapi saya pikir ada baiknya mengatakan mengapaMath.random()
fungsi taints yang menggunakannya.Seperti semua pembuat nomor pseudorandom,
Math.random()
dimulai dengan nilai "seed". Kemudian menggunakan nilai itu sebagai titik awal untuk rangkaian manipulasi bit tingkat rendah atau operasi lain yang menghasilkan keluaran yang tidak dapat diprediksi (tetapi tidak benar - benar acak ).Dalam JavaScript, proses yang terlibat bergantung pada implementasi, dan tidak seperti banyak bahasa lain, JavaScript menyediakan tidak cara untuk memilih benih :
Itulah mengapa fungsi ini tidak murni: JavaScript pada dasarnya menggunakan parameter fungsi implisit yang tidak dapat Anda kendalikan. Ini membaca parameter itu dari data yang dihitung dan disimpan di tempat lain, dan karena itu melanggar aturan # 2 dalam definisi Anda.
Jika Anda ingin menjadikan ini fungsi murni, Anda dapat menggunakan salah satu generator nomor acak alternatif yang dijelaskan di sini . Panggil generator itu
seedable_random
. Dibutuhkan satu parameter (benih) dan mengembalikan nomor "acak". Tentu saja, angka ini sama sekali tidak acak; itu secara unik ditentukan oleh benih. Itulah mengapa ini adalah fungsi murni. Keluaran dariseedable_random
hanya "acak" dalam arti sulit memprediksi keluaran berdasarkan masukan.Versi murni dari fungsi ini perlu mengambil tiga parameter:
Untuk tiga kali lipat
(min, max, seed)
parameter apa pun, ini akan selalu mengembalikan hasil yang sama.Catatan bahwa jika Anda ingin output
seedable_random
menjadi benar-benar acak, Anda akan perlu untuk menemukan cara untuk mengacak benih! Dan strategi apa pun yang Anda gunakan pasti tidak murni, karena itu mengharuskan Anda mengumpulkan informasi dari sumber di luar fungsi Anda. Seperti yang diingatkan oleh mtraceur dan jpmc26 , ini mencakup semua pendekatan fisik: generator nomor acak perangkat keras , webcam dengan penutup lensa , pengumpul kebisingan atmosfer - bahkan lampu lava . Semua ini melibatkan penggunaan data yang dihitung dan disimpan di luar fungsi.sumber
Math.random
tidak menggunakan PRNG tetapi diimplementasikan menggunakan perangkat keras RNG? RNG perangkat keras tidak benar-benar memiliki status dalam arti normal, tetapi ia menghasilkan nilai acak (dan dengan demikian output fungsi masih berbeda terlepas dari inputnya), bukan?Fungsi murni adalah fungsi yang nilai kembaliannya hanya ditentukan oleh nilai masukannya, tanpa efek samping yang dapat diamati
Dengan menggunakan Math.random, Anda menentukan nilainya dengan sesuatu selain nilai input. Ini bukan fungsi murni.
sumber
sumber
Tidak, ini bukan fungsi murni karena keluarannya tidak hanya bergantung pada masukan yang disediakan (Math.random () dapat mengeluarkan nilai apa pun), sedangkan fungsi murni harus selalu menampilkan nilai yang sama untuk masukan yang sama.
Jika suatu fungsi murni, aman untuk mengoptimalkan beberapa panggilan dengan input yang sama dan hanya menggunakan kembali hasil panggilan sebelumnya.
PS bagi saya setidaknya dan bagi banyak orang lainnya, redux membuat istilah fungsi murni populer.Langsung dari dokumen redux :
sumber
Dari sudut pandang matematis, tanda tangan Anda tidak
tapi
dimana
environment
mampu memberikan hasilMath.random()
. Dan sebenarnya menghasilkan nilai acak akan mengubah lingkungan sebagai efek samping, jadi Anda juga mengembalikan lingkungan baru, yang tidak sama dengan yang pertama!Dengan kata lain, jika Anda memerlukan jenis input yang tidak berasal dari argumen awal (
<number, number>
bagian), maka Anda perlu disediakan lingkungan eksekusi (yang dalam contoh ini menyediakan status untukMath
). Hal yang sama berlaku untuk hal lain yang disebutkan oleh jawaban lain, seperti I / O atau semacamnya.Sebagai analogi, Anda juga dapat memperhatikan ini adalah bagaimana pemrograman berorientasi objek dapat direpresentasikan - jika kita katakan, mis
lalu sebenarnya kami menggunakan
dengan objek yang metodenya dipanggil menjadi bagian dari lingkungan. Dan mengapa
SomeClass
bagian dari hasil? Karenasomething
keadaan bisa berubah juga!sumber
test: <environment, number, number> -> <environment, number>
seharusnyaa.F(b, c)
dapat dilihat sebagai gula sintaksisF(a, b, c)
dengan aturan khusus untuk dikirim ke definisi yang kelebihan bebanF
berdasarkan jenisa
(ini sebenarnya bagaimana Python merepresentasikannya). Tetapia
masih eksplisit di kedua notasi, sedangkan lingkungan dalam fungsi non-murni tidak pernah disebutkan dalam kode sumber.Fungsi murni selalu mengembalikan nilai yang sama untuk masukan yang sama. Fungsi murni dapat diprediksi dan transparan referensial yang berarti bahwa kita dapat mengganti pemanggilan fungsi dengan keluaran yang dikembalikan dan itu tidak akan mengubah kerja program.
https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md
sumber
Selain jawaban lain yang dengan benar menunjukkan bagaimana fungsi ini non-deterministik, ini juga memiliki efek samping: ini akan menyebabkan panggilan di masa mendatang
math.random()
untuk mengembalikan jawaban yang berbeda. Dan generator bilangan acak yang tidak memiliki properti itu biasanya akan melakukan beberapa jenis I / O, seperti membaca dari perangkat acak yang disediakan oleh OS. Salah satunya adalah verboten untuk fungsi murni.sumber
Tidak, tidak. Anda tidak dapat mengetahui hasilnya sama sekali, jadi potongan kode ini tidak dapat diuji. Untuk membuat kode itu dapat diuji, Anda perlu mengekstrak komponen yang menghasilkan nomor acak:
Sekarang, Anda dapat memalsukan generator dan menguji kode Anda dengan benar:
Dan di kode "produksi" Anda:
sumber
util.Random
, yang dapat Anda seed di awal uji coba untuk mengulangi perilaku lama atau untuk pengujian baru (tetapi berulang). Jika multi-threading, Anda mungkin dapat melakukan ini di utas utama dan menggunakannyaRandom
untuk menyemai utas-lokal berulangRandom
. Namun, seperti yang saya pahami,test(int,int,Random)
tidak dianggap murni karena mengubah keadaanRandom
.Apakah Anda setuju dengan yang berikut:
setara dengan
?
Soalnya, definisi murni adalah fungsi yang keluarannya tidak berubah dengan apa pun selain masukannya. Jika kami mengatakan bahwa JavaScript memiliki cara untuk memberi tag pada fungsi murni dan memanfaatkannya, pengoptimal akan diizinkan untuk menulis ulang ekspresi pertama sebagai yang kedua.
Saya memiliki pengalaman praktis dengan ini. SQL server diperbolehkan
getdate()
dannewid()
dalam fungsi "murni" dan pengoptimal akan menghapus panggilan sesuka hati. Terkadang ini akan melakukan sesuatu yang bodoh.sumber