当前位置:  开发笔记 > 编程语言 > 正文

让我们在Clojure中结束

如何解决《让我们在Clojure中结束》经验,为你挑选了3个好方法。

我知道它们是不同的,因为一个用于设置*compile-path*,一个不用.但是,我需要帮助他们为什么不同.

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



1> Brian Carper..:

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

动态绑定意味着binding表单中的代码和代码调用的任何代码(即使不在本地词法范围内)将看到新的绑定.

鉴于:

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

binding实际上为a创建一个动态绑定,Varlet只用本地别名隐藏var:

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

binding可以使用限定名称(因为它在Vars上运行)并且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

另见Vars,让.


这加上http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping确实提升了我的理解力.谢谢你,先生!

2> Marc..:

let vs binding的另一个语法差异:

对于绑定,在将任何初始值绑定到变量之前评估所有初始值.这与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



3> Yuval Adam..:

binding 将值绑定到每线程全局环境中的名称

如您所述,let为所述绑定创建一个新范围.

推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有