2009-10-06 12 views
65

Entiendo que son diferentes ya que uno funciona para establecer *compile-path* y uno no. Sin embargo, necesito ayuda con por qué son diferentes.Deje versus Vinculación en Clojure

let crea un nuevo ámbito con los enlaces proporcionados, pero binding ...?

Respuesta

99

let crea un alias inmutable de ámbito léxico para cierto 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 binding y cualquier código que llame ese código (incluso si no está dentro del alcance léxico local) verá el nuevo enlace.

dado:

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

binding realidad crea unión para un Var pero let sólo sombras de la var con un alias local una dinámica:

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 pueden:

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 -los enlaces introducidos no son modificables. binding fijaciones -introduced 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 vs enlace 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.

+4

Esto más http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping muy avanzado mi entendimiento. ¡Gracias Señor! – Carl

+0

La x debe estar vinculada con la ^: sugerencia dinámica para no lanzar un error, me beleave. – WeGi

8

binding se une un valor a un nombre en el medio ambiente mundial por subproceso

Como usted ha mencionado, let crea un nuevo ámbito de dichos enlaces.

10

Una diferencia sintáctica más, para alquiler frente a la unión:

Para la unión, todos los valores iniciales se evalúan antes que cualquiera de ellos están ligados 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 
+0

Necesita ^: dynamic para definir x a 0 (también dinámicamente) para que su segundo ejemplo funcione. – John