Ich verstehe, dass sie unterschiedlich sind, da man für die Einstellung arbeitet *compile-path*
und man nicht. Ich brauche jedoch Hilfe, warum sie anders sind.
let
erstellt einen neuen Bereich mit den angegebenen Bindungen, aber binding
...?
Antworten:
let
Erstellt einen unveränderlichen Alias mit lexikalischem Gültigkeitsbereich für einen bestimmten Wert. binding
erstellt für einige eine Bindung mit dynamischem Gültigkeitsbereich Var
.
Dynamische Bindung bedeutet, dass der Code in Ihrem binding
Formular und jeder Code, den dieser Code aufruft (auch wenn er nicht im lokalen lexikalischen Bereich liegt), die neue Bindung sehen.
Gegeben:
user> (def ^:dynamic x 0)
#'user/x
binding
Erstellt tatsächlich eine dynamische Bindung für a Var
, let
schattiert die Variable jedoch nur mit einem lokalen Alias:
user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0
binding
kann qualifizierte Namen verwenden (da es mit Var
s arbeitet) und let
kann nicht:
user> (binding [user/x 1] (var-get #'x))
1
user> (let [user/x 1] (var-get #'x))
; Evaluation aborted.
;; Can't let qualified name: user/x
let
eingeführte Bindungen sind nicht veränderlich. binding
eingeführte Bindungen sind thread-lokal veränderbar:
user> (binding [x 1] (set! x 2) x)
2
user> (let [x 1] (set! x 2) x)
; Evaluation aborted.
;; Invalid assignment target
Lexikalische vs. dynamische Bindung:
user> (defn foo [] (println x))
#'user/foo
user> (binding [x 1] (foo))
1
nil
user> (let [x 1] (foo))
0
nil
Ein weiterer syntaktischer Unterschied zwischen let und bindung:
Für die Bindung werden alle Anfangswerte ausgewertet, bevor sie an die Variablen gebunden werden. Dies unterscheidet sich von let, wo Sie den Wert eines vorherigen "Alias" in einer nachfolgenden Definition verwenden können.
user=>(let [x 1 y (+ x 1)] (println y))
2
nil
user=>(def y 0)
user=>(binding [x 1 y (+ x 1)] (println y))
1
nil
binding
bindet einen Wert an einen Namen in der globalen Umgebung pro Thread
Wie Sie bereits erwähnt haben, let
wird ein neuer Bereich für diese Bindungen erstellt.