binding clojure let

binding - Deje versus enlace en Clojure



let (3)

Entiendo que son diferentes ya que uno funciona para establecer *compile-path* y uno no. Sin embargo, necesito ayuda con por qué son diferentes.

let crea un nuevo alcance con los enlaces dados, pero binding ...?


Una diferencia sintáctica más para let versus binding:

Para el enlace, todos los valores iniciales se evalúan antes de que cualquiera de ellos se vincule a los vars. Esto es diferente de let, donde puede usar el valor de un "alias" anterior 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 vincula un valor a un nombre en el entorno global por subproceso

Como mencionaste, crea un nuevo alcance para dichas vinculaciones.


let crea un alias inmutable de ámbito léxico para algún valor. binding crea un enlace de ámbito dinámico para algunos Var .

La vinculación dinámica significa que el código dentro de su formulario de binding y cualquier código que llame ese código (incluso si no está en el alcance léxico local) verá el nuevo enlace.

Dado:

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

binding realmente crea un enlace dinámico para un Var pero solo let sombrear la var con un alias local:

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

binding puede usar nombres calificados (ya que opera en Var s) y let 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

let las consolidaciones introducidas no sean mutables. binding -enlaces introducidos son thread-local mutable:

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

Enlace léxico vs. dinámico:

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

Ver también Vars , let .