我知道它们是不同的,因为一种适用于设置,*compile-path*
而另一种不适用。但是,我需要帮助他们为什么与众不同。
let
使用给定的绑定创建一个新的作用域,但是binding
...?
Answers:
let
为某些值创建词法范围内的不可变别名。 binding
为some创建一个动态范围的绑定Var
。
动态绑定意味着binding
表单内的代码以及该代码调用的任何代码(即使不在本地词法范围内)也将看到新的绑定。
鉴于:
user> (def ^:dynamic x 0)
#'user/x
binding
实际上为创建了一个动态绑定,Var
但let
仅使用本地别名遮盖了var:
user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0
binding
可以使用限定名称(因为它在上运行Var
),let
并且不能:
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
词汇绑定与动态绑定:
user> (defn foo [] (println x))
#'user/foo
user> (binding [x 1] (foo))
1
nil
user> (let [x 1] (foo))
0
nil