Ich bin neu in Haskell und ich bin sehr verwirrt von Where vs. Let . Sie scheinen beide einen ähnlichen Zweck zu erfüllen. Ich habe einige Vergleiche zwischen Where vs. Let gelesen, aber ich habe Probleme zu erkennen, wann ich sie verwenden soll. Könnte jemand bitte einen Kontext oder vielleicht ein paar Beispiele angeben, die zeigen, wann man sie übereinander verwendet?
Wo gegen lassen
Eine
where
Klausel kann nur auf der Ebene einer Funktionsdefinition definiert werden. Normalerweise ist das identisch mit demlet
Definitionsumfang. Der einzige Unterschied besteht darin, wann Wachen verwendet werden . Der Geltungsbereich derwhere
Klausel erstreckt sich über alle Wachen. Im Gegensatz dazu ist der Umfang eineslet
Ausdrucks nur die aktuelle Funktionsklausel und ggf. der Schutz.
Das Haskell-Wiki ist sehr detailliert und bietet verschiedene Fälle, verwendet jedoch hypothetische Beispiele. Ich finde die Erklärungen für einen Anfänger zu kurz.
Vorteile von Let :
f :: State s a
f = State $ \x -> y
where y = ... x ...
funktioniert nicht, da sich where auf die Musterübereinstimmung f = bezieht, wobei kein x im Gültigkeitsbereich liegt. Wenn Sie dagegen mit let begonnen hätten, hätten Sie keine Probleme.
Haskell Wiki über die Vorteile von Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Vorteile von Wo :
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)
Das Haskell-Wiki erwähnt, dass die Where- Klausel deklarativ ist, während der Let- Ausdruck expressiv ist. Wie verhalten sie sich neben dem Stil anders?
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 ...
- Im ersten Beispiel, warum ist der Bereich Einlassen, aber wo nicht?
- Ist es möglich, Wo auf das erste Beispiel anzuwenden ?
- Können einige dies auf reale Beispiele anwenden, bei denen die Variablen tatsächliche Ausdrücke darstellen?
- Gibt es eine allgemeine Faustregel, die zu befolgen ist, wann sie verwendet werden sollen?
Aktualisieren
Für diejenigen, die später von diesem Thread kommen, fand ich die beste Erklärung hier: " Eine sanfte Einführung in Haskell ".
Lassen Sie Ausdrücke.
Haskells let-Ausdrücke sind immer dann nützlich, wenn ein verschachtelter Satz von Bindungen erforderlich ist. Betrachten Sie als einfaches Beispiel:
let y = a*b f x = (x+y)/y in f c + f d
Der Satz von Bindungen, der durch einen let-Ausdruck erzeugt wird, ist gegenseitig rekursiv, und Musterbindungen werden als faule Muster behandelt (dh sie tragen ein implizites ~). Die einzigen zulässigen Deklarationen sind Typensignaturen, Funktionsbindungen und Musterbindungen.
Where-Klauseln.
Manchmal ist es zweckmäßig, Bindungen über mehrere geschützte Gleichungen hinweg zu erfassen, was eine where-Klausel erfordert:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Beachten Sie, dass dies nicht mit einem let-Ausdruck möglich ist, der nur den darin enthaltenen Ausdruck abdeckt. Eine where-Klausel ist nur auf der obersten Ebene eines Satzes von Gleichungen oder eines Fallausdrucks zulässig. Die gleichen Eigenschaften und Einschränkungen für Bindungen in let-Ausdrücken gelten für diejenigen in where-Klauseln. Diese beiden Formen des verschachtelten Bereichs scheinen sehr ähnlich zu sein, aber denken Sie daran, dass ein let-Ausdruck ein Ausdruck ist, während eine where-Klausel dies nicht ist - er ist Teil der Syntax von Funktionsdeklarationen und case-Ausdrücken.
let
undwhere
als ich anfing, Haskell zu lernen. Ich denke, der beste Weg, dies zu verstehen, besteht darin, zu erkennen, dass es kaum einen Unterschied zwischen den beiden gibt und daher kein Grund zur Sorge besteht. Die Bedeutung vonwhere
gegebenlet
durch eine sehr einfache mechanische Transformation gegeben. Siehe haskell.org/onlinereport/decls.html#sect4.4.3.2. Diese Transformation dient eigentlich nur zur Vereinfachung der Notation.f = body where x = xbody; y = ybody ...
bedeutetf = let x = xbody; y = ybody ... in body
case .... of ... where
Ausdruck irgendwie in einen Ausdruck umzuwandeln ? Da bin ich mir nicht sicher.Antworten:
1: Das Problem im Beispiel
ist der Parameter
x
. Dinge in derwhere
Klausel können sich nur auf die Parameter der Funktionf
(es gibt keine) und Dinge in äußeren Bereichen beziehen .2: Um a
where
im ersten Beispiel zu verwenden, können Sie eine zweite benannte Funktion einführen, die dasx
als Parameter verwendet, wie folgt:oder so:
3: Hier ist ein vollständiges Beispiel ohne die
...
's:4: Wann zu verwenden
let
oderwhere
ist Geschmackssache. Ich benutzelet
, um eine Berechnung hervorzuheben (indem ich sie nach vorne verschiebe) undwhere
um den Programmablauf hervorzuheben (indem ich die Berechnung nach hinten verschiebe).quelle
Während es den technischen Unterschied in Bezug auf Wachen gibt, auf den Ephemient hingewiesen hat, gibt es auch einen konzeptionellen Unterschied darin, ob Sie die Hauptformel mit den unten definierten zusätzlichen Variablen (
where
) vorab stellen möchten oder ob Sie alles vorab definieren und die Formel setzen möchten unten (let
). Jeder Stil hat eine andere Betonung, und Sie sehen, dass beide in Mathepapieren, Lehrbüchern usw. verwendet werden. Im Allgemeinen sollten Variablen, die so unintuitiv sind, dass die Formel ohne sie keinen Sinn ergibt, oben definiert werden. Variablen, die aufgrund des Kontexts oder ihrer Namen intuitiv sind, sollten unten definiert werden. Zum Beispiel ist im hasVowel-Beispiel von ephemient die Bedeutung vonvowels
offensichtlich und muss daher nicht über seiner Verwendung definiert werden (ohne Berücksichtigung der Tatsache, dasslet
dies aufgrund des Schutzes nicht funktionieren würde).quelle
Legal:
Nicht legal:
Legal:
Nicht legal: (im Gegensatz zu ML)
quelle
hasVowel = let^M vowels = "AEIOUaeiou"^M in ...
(^M
ist Newline)Ich fand dieses Beispiel von LYHFGG hilfreich:
let
ist ein Ausdruck, mit dem Sielet
überall (!) einfügen können, wohin Ausdrücke gehen können.Mit anderen Worten, im obigen Beispiel ist es nicht möglich,
where
einfach zu ersetzenlet
(ohne vielleicht einen ausführlicherencase
Ausdruck in Kombination mit zu verwendenwhere
).quelle
Leider sind die meisten Antworten hier für Anfänger zu technisch.
LHYFGG hat ein relevantes Kapitel darüber - das Sie lesen sollten, wenn Sie es noch nicht getan haben, aber im Wesentlichen:
where
ist nur ein syntaktisches Konstrukt (kein Zucker ), das nur bei Funktionsdefinitionen nützlich ist .let ... in
ist ein Ausdruck selbst , daher können Sie sie überall dort verwenden, wo Sie einen Ausdruck einfügen können. Als Ausdruck selbst kann er nicht dazu verwendet werden, Dinge für Wachen zu binden.Schließlich können Sie auch
let
in Listenverständnissen verwenden:quelle