2009-10-06 6 views
65

Ich verstehe, dass sie anders sind, da man für die Einstellung *compile-path* arbeitet und man nicht funktioniert. Ich brauche jedoch Hilfe, warum sie anders sind.Let vs. Binden in Clojure

let erstellt einen neuen Bereich mit den angegebenen Bindungen, aber binding ...?

Antwort

99

let erstellt einen lexikalisch begrenzten unveränderlichen Alias ​​für einen bestimmten Wert. binding erstellt eine dynamisch begrenzte Bindung für einige Var.

Dynamische Bindung bedeutet, dass der Code in Ihrem binding Formular und Code, der diesen Code aufruft (auch wenn nicht im lokalen lexikalischen Bereich) die neue Bindung sehen wird.

Gegeben:

user> (def ^:dynamic x 0) 
#'user/x 

binding tatsächlich schafft ein dynamisches für eine Var Bindung aber let Schatten nur die var mit einem lokalen Alias:

user> (binding [x 1] (var-get #'x)) 
1 
user> (let [x 1] (var-get #'x)) 
0 

binding können qualifizierte Namen verwenden (da es arbeitet auf Var s) 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 änderbar. binding -introduced Bindungen sind gewinde lokal veränderliches:

user> (binding [x 1] (set! x 2) x) 
2 
user> (let [x 1] (set! x 2) x) 
; Evaluation aborted. 
;; Invalid assignment target 

Lexical vs. dynamische Bindung:

user> (defn foo [] (println x)) 
#'user/foo 
user> (binding [x 1] (foo)) 
1 
nil 
user> (let [x 1] (foo)) 
0 
nil 

Siehe auch Vars, let.

+4

Dieses Plus http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping wirklich mein Verständnis vorangetrieben. Danke mein Herr! – Carl

+0

Das x muss mit dem ^: dynamischen Hinweis verbunden sein, um keinen Fehler zu erzeugen, ich bleibe. – WeGi

8

binding bindet Wert auf einen Namen in der Pro-Thread globalen Umwelt

Wie Sie erwähnt, schafft let einen neuen Bereich für die Bindung.

10

Noch ein syntaktischer Unterschied für let vs Bindung:

Für die Bindung, die alle der Anfangswert ausgewertet werden, bevor einer von ihnen an die Vars gebunden ist. 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 
+0

Sie brauchen ^: dynamisch, um x (auch dynamisch) auf 0 zu setzen, damit Ihr zweites Beispiel funktioniert. – John