问题描述
我知道它们是不同的,因为一种用于设置 *compile-path*
而另一种则没有.但是,我需要帮助解释为什么它们不同.
I understand that they're different since one works for setting *compile-path*
and one doesn't. However, I need help with why they're different.
let
使用给定的绑定创建一个新的作用域,但是 binding
...?
let
creates a new scope with the given bindings, but binding
...?
推荐答案
let
为某个值创建一个词法作用域的不可变别名.binding
为某些 Var
创建一个动态范围的绑定.
let
creates a lexically scoped immutable alias for some value. binding
creates a dynamically scoped binding for some Var
.
动态绑定意味着 binding
表单中的代码以及该代码调用的任何代码(即使不在本地词法范围内)都将看到新的绑定.
Dynamic binding means that the code inside your binding
form and any code which that code calls (even if not in the local lexical scope) will see the new binding.
给定:
user> (def ^:dynamic x 0)
#'user/x
binding
实际上为 Var
创建了一个动态绑定,但 let
只用本地别名隐藏 var:
binding
actually creates a dynamic binding for a Var
but let
only shadows the var with a local alias:
user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0
binding
可以使用限定名称(因为它对 Var
进行操作)而 let
不能:
binding
can use qualified names (since it operates on Var
s) and let
can't:
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
引入的绑定是线程本地可变的:
let
-introduced bindings are not mutable. binding
-introduced bindings are thread-locally mutable:
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
这篇关于Clojure 中的让与绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!