Deje vs Encuadernación en Clojure
Pregunta
Yo entiendo que son diferentes ya que se trabaja para establecer *compile-path*
y el otro no. Sin embargo, necesito ayuda con eso que son diferentes.
let
crea un nuevo ámbito con los enlaces dados, pero binding
...?
Solución
let
crea un alias de inmutable ámbito léxico para un cierto valor. binding
crea un ámbito dinámico vinculante para algunos Var
.
Dynamic medios de unión que el código dentro de su formulario binding
y cualquier código que llama a ese código (aunque no sea en el ámbito léxico local) verán la nueva unión.
Teniendo en cuenta:
user> (def ^:dynamic x 0)
#'user/x
binding
en realidad crea un enlace para un Var
dinámico, pero let
sólo sombras de la var con un alias local:
user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0
binding
puede utilizar nombres cualificados (ya que opera en Var
s) y let
no puede:
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
fijaciones let
-introducido no son mutables. encuadernaciones binding
a introducir son hilos localmente mutable:
user> (binding [x 1] (set! x 2) x)
2
user> (let [x 1] (set! x 2) x)
; Evaluation aborted.
;; Invalid assignment target
Léxico frente a la unión dinámica:
user> (defn foo [] (println x))
#'user/foo
user> (binding [x 1] (foo))
1
nil
user> (let [x 1] (foo))
0
nil
Otros consejos
Una de las diferencias más sintáctica, para alquiler frente a la unión:
Para la unión, todos los valores iniciales se evalúan antes que cualquiera de ellos se unen a la vars. Esto es diferente de let, donde se puede utilizar el valor de una anterior "alias" en una definición posterior.
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
une un valor a un nombre en el medio ambiente mundial per-hilo
Como se ha mencionado, let
crea un nuevo ámbito de dichos enlaces.