我知道它们是不同的,因为一个用于设置 *compile-path* 但也有人没有。但是,我需要帮助了解它们为何不同。

let 使用给定的绑定创建一个新范围,但是 binding...?

有帮助吗?

解决方案

let 为某些值创建词法范围的不可变别名。 binding 为某些创建动态范围的绑定 Var.

动态绑定意味着你的代码里面 binding form 以及该代码调用的任何代码(即使不在本地词法范围内)都将看到新的绑定。

鉴于:

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

binding 实际上创建了一个动态绑定 Varlet 仅使用本地别名隐藏 var:

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

binding 可以使用限定名称(因为它运行在 Varlet 不能:

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

也可以看看 瓦尔斯, .

其他提示

为让一个更句法差Vs结合:

有关的结合,所有的初始值之前,它们中的任何被绑定到VARS评价。这是从让,在这里可以在随后的定义中使用的先前“别名”的值不同。

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结合在每线程全球环境的值,以一个名称

如你所提到的,let创建用于所述绑定一个新的范围。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top