Saya baru mengenal Haskell dan saya sangat bingung dengan Where vs. Let . Keduanya sepertinya memberikan tujuan yang sama. Saya telah membaca beberapa perbandingan antara Where vs. Let tetapi saya kesulitan membedakan kapan harus menggunakan masing-masing. Bisakah seseorang memberikan beberapa konteks atau mungkin beberapa contoh yang menunjukkan kapan harus menggunakan salah satu dari yang lain?
Dimana vs.
Sebuah
where
klausul hanya dapat didefinisikan pada tingkat definisi fungsi. Biasanya, itu identik dengan ruang lingkuplet
definisi. Satu-satunya perbedaan adalah saat penjaga digunakan . Cakupanwhere
klausul meluas ke semua penjaga. Sebaliknya, cakupanlet
ekspresi hanya klausa fungsi saat ini dan penjaga, jika ada.
The Haskell Wiki sangat rinci dan menyediakan berbagai kasus tetapi menggunakan contoh hipotetis. Saya merasa penjelasannya terlalu singkat untuk pemula.
Keuntungan dari Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
tidak akan bekerja, karena where mengacu pada pola yang cocok dengan f =, di mana tidak ada x dalam ruang lingkup. Sebaliknya, jika Anda memulai dengan biarkan, maka Anda tidak akan mengalami kesulitan.
Haskell Wiki tentang Keuntungan Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Keuntungan Dimana :
f x
| cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
where
a = w x
f x
= let a = w x
in case () of
_ | cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
Wiki Haskell menyebutkan bahwa klausa Where bersifat deklaratif sedangkan ekspresi Let ekspresif. Selain gaya, bagaimana mereka tampil berbeda?
Declaration style | Expression-style
--------------------------------------+---------------------------------------------
where clause | let expression
arguments LHS: f x = x*x | Lambda abstraction: f = \x -> x*x
Pattern matching: f [] = 0 | case expression: f xs = case xs of [] -> 0
Guards: f [x] | x>0 = 'a' | if expression: f [x] = if x>0 then 'a' else ...
- Pada contoh pertama mengapa Let in scope tapi Where tidak?
- Apakah mungkin untuk menerapkan Di mana contoh pertama?
- Bisakah beberapa menerapkan ini pada contoh nyata di mana variabel mewakili ekspresi sebenarnya?
- Apakah ada aturan umum yang harus diikuti kapan harus menggunakan masing-masing?
Memperbarui
Bagi mereka yang datang melalui utas ini nanti, saya menemukan penjelasan terbaik dapat ditemukan di sini: " Pengantar yang Lembut untuk Haskell ".
Biarkan Ekspresi.
Ekspresi let Haskell berguna setiap kali diperlukan kumpulan bertingkat dari binding. Sebagai contoh sederhana, pertimbangkan:
let y = a*b f x = (x+y)/y in f c + f d
Himpunan binding yang dibuat oleh ekspresi let saling rekursif, dan binding pola diperlakukan sebagai pola malas (yaitu, membawa ~ implisit). Satu-satunya jenis deklarasi yang diizinkan adalah tanda tangan tipe, binding fungsi, dan binding pola.
Dimana Klausul.
Kadang-kadang lebih mudah untuk mengikat lingkup pada beberapa persamaan yang dilindungi, yang membutuhkan klausa where:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Perhatikan bahwa ini tidak bisa dilakukan dengan ekspresi let, yang hanya mencakup ekspresi yang diapitnya. Klausa where hanya diperbolehkan di tingkat atas dari kumpulan persamaan atau ekspresi kasus. Properti dan batasan yang sama pada binding di biarkan ekspresi diterapkan ke dalam klausa where. Kedua bentuk lingkup bersarang ini tampak sangat mirip, tetapi ingat bahwa ekspresi let adalah ekspresi, sedangkan klausa where bukan - itu adalah bagian dari sintaks deklarasi fungsi dan ekspresi kasus.
let
danwhere
saat pertama kali belajar Haskell. Saya pikir cara terbaik untuk memahaminya adalah dengan menyadari bahwa ada sangat sedikit perbedaan antara keduanya, dan oleh karena itu tidak ada yang perlu dikhawatirkan. Arti yangwhere
diberikan dalam pengertianlet
melalui transformasi mekanis yang sangat sederhana. Lihat haskell.org/onlinereport/decls.html#sect4.4.3.2 Transformasi ini ada hanya untuk kenyamanan notasi.f = body where x = xbody; y = ybody ...
artinyaf = let x = xbody; y = ybody ... in body
case .... of ... where
ekspresi? Saya tidak yakin tentang ini.Jawaban:
1: Masalah di contoh
adalah parameternya
x
. Hal-hal dalamwhere
klausa hanya dapat merujuk ke parameter fungsif
(tidak ada) dan hal-hal di cakupan luar.2: Untuk menggunakan a
where
pada contoh pertama, Anda dapat memperkenalkan fungsi bernama kedua yang mengambilx
parameter sebagai, seperti ini:atau seperti ini:
3: Berikut adalah contoh lengkap tanpa
...
's:4: Kapan harus digunakan
let
atauwhere
tergantung selera. Saya menggunakanlet
untuk menekankan komputasi (dengan memindahkannya ke depan) danwhere
untuk menekankan aliran program (dengan memindahkan komputasi ke belakang).sumber
Meskipun ada perbedaan teknis sehubungan dengan pelindung yang ditunjukkan oleh sementara, ada juga perbedaan konseptual dalam hal apakah Anda ingin meletakkan rumus utama di muka dengan variabel tambahan yang ditentukan di bawah (
where
) atau apakah Anda ingin mendefinisikan semuanya di muka dan meletakkan rumusnya di bawah (let
). Setiap gaya memiliki penekanan yang berbeda dan Anda melihat keduanya digunakan dalam makalah matematika, buku teks, dll. Umumnya, variabel yang cukup tidak intuitif sehingga rumus tidak masuk akal tanpanya harus didefinisikan di atas; variabel yang intuitif karena konteks atau namanya harus ditentukan di bawah. Misalnya, dalam contoh hasVowel ephemient, artinyavowels
sudah jelas dan karenanya tidak perlu didefinisikan di atas penggunaannya (mengabaikan fakta bahwalet
tidak akan berfungsi karena penjaga).sumber
Hukum:
Tidak sah:
Hukum:
Tidak legal: (tidak seperti ML)
sumber
hasVowel = let^M vowels = "AEIOUaeiou"^M in ...
(^M
baris baru)Saya menemukan contoh dari LYHFGG ini bermanfaat:
let
adalah ekspresi sehingga Anda dapat meletakkannya dilet
mana saja (!) mana ekspresi bisa pergi.Dengan kata lain, dalam contoh di atas tidak mungkin digunakan
where
untuk sekadar menggantilet
(tanpa mungkin menggunakan beberapacase
ekspresi verbose yang digabungkan denganwhere
).sumber
Sayangnya, sebagian besar jawaban di sini terlalu teknis untuk pemula.
LHYFGG memiliki bab yang relevan -yang harus Anda baca jika Anda belum melakukannya, tetapi pada intinya:
where
hanyalah konstruksi sintaksis (bukan gula ) yang hanya berguna pada definisi fungsi .let ... in
adalah ekspresi itu sendiri , sehingga Anda dapat menggunakannya di mana pun Anda dapat meletakkan ekspresi. Menjadi ekspresi itu sendiri, itu tidak bisa digunakan untuk mengikat sesuatu untuk penjaga.Terakhir, Anda juga dapat menggunakan
let
dalam pemahaman daftar:sumber