让我们与Clojure绑定吧
我明白,他们是不同的,因为一个工程设置*compile-path*
而不是。 不过,我需要帮助他们为什么不同。
let
定的绑定创build一个新的作用域,但binding
…?
let
为某个值创build一个词法范围的不可变的别名。 binding
为某些Var
创build一个dynamic范围的绑定。
dynamic绑定意味着binding
表单中的代码和代码调用的任何代码(即使不在本地词法作用域中)都将看到新的绑定。
鉴于:
user> (def ^:dynamic x 0) #'user/x
binding
实际上为Var
创build了一个dynamic绑定,但只let
使用本地别名来隐藏var:
user> (binding [x 1] (var-get #'x)) 1 user> (let [x 1] (var-get #'x)) 0
binding
可以使用限定名称(因为它在Var
s上运行)并且不能:
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
引入的绑定是不可变的。 binding
引入的绑定是线程局部可变的:
user> (binding [x 1] (set! x 2) x) 2 user> (let [x 1] (set! x 2) x) ; Evaluation aborted. ;; Invalid assignment target
词法与dynamic绑定:
user> (defn foo [] (println x)) #'user/foo user> (binding [x 1] (foo)) 1 nil user> (let [x 1] (foo)) 0 nil
参见瓦尔斯 , 让 。
让let vs绑定更多的语法差异:
对于绑定,所有的初始值在任何绑定到variables之前被评估。 这不同于let,在后面的定义中可以使用前一个“别名”的值。
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
将值binding
到每个线程的全局环境中的名称
正如你所提到的, let
为这个绑定创build一个新的范围。