Lasciate vs. Legatura in Clojure
Domanda
Mi rendo conto che sono diversi in quanto si lavora per l'impostazione *compile-path*
e uno non lo fa. Tuttavia, ho bisogno di aiuto con il motivo per cui sono diversi.
let
crea un nuovo ambito con le associazioni riportate, ma binding
...?
Soluzione
let
crea un alias immutabile con scope lessicale per un certo valore. binding
crea un scope dinamico vincolante per qualche Var
.
dinamico mezzi vincolante che il codice all'interno del modulo binding
e qualsiasi codice che chiama il codice (anche se non in ambito lessicale locale) vedrà la nuova associazione.
Data:
user> (def ^:dynamic x 0)
#'user/x
binding
crea effettivamente una dinamica vincolante per un Var
ma let
ombre solo la var con un alias locale:
user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0
binding
può utilizzare nomi qualificati (dal momento che opera su Var
s) e let
non può:
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
attacchi let
-introdotto, non sono mutabili. binding binding
-introdotto sono thread-localmente mutevole:
user> (binding [x 1] (set! x 2) x)
2
user> (let [x 1] (set! x 2) x)
; Evaluation aborted.
;; Invalid assignment target
lessicale vs. binding dinamico:
user> (defn foo [] (println x))
#'user/foo
user> (binding [x 1] (foo))
1
nil
user> (let [x 1] (foo))
0
nil
Altri suggerimenti
Ancora una differenza sintattica per Let vs rilegatura:
Per la rilegatura, tutti i valori iniziali vengono valutati prima di qualsiasi di essi sono legati al Vars. Questo è diverso da let, dove è possibile utilizzare il valore di un precedente "alias" in una definizione successiva.
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
si lega un valore a un nome nell'ambiente globale pro-filo
Come lei ha ricordato, let
crea un nuovo ambito per detti attacchi.