在Clojure中,通过闭包可以通过with-local-vars
定义变量吗?
考虑以下示例:
(defn foo []
(with-local-vars [bar 10]
(fn [] @bar)))
((foo))
结果如下:
#object[clojure.lang.Var$Unbound 0x131f68d8 "Unbound: #<Var: --unnamed-->"]
(相反,我期待获得10
。)
C.f。以下内容:
(defn foo []
(with-local-vars [bar 10] @bar))
(foo)
结果:10
。
基于documentation,我不清楚,如果在Clojure中使用本地变量是有效的,但我怀疑答案是否定的。你能否确认一下(或反驳,并解释我在第一个例子中做错了什么)?如果我的假设是明确的(即局部变量不能用于闭包),那么解释原因是什么?
答案 0 :(得分:6)
with-local-vars
的文档在这里似乎并不是特别清楚。它只是说它为变量创建了线程局部绑定,但是在退出with-local-vars
范围时没有说明它们发生了什么。
相比之下,with-bindings
documentation明确表示在离开该范围时会弹出线程局部绑定。
如果您查看源代码,可以看到with-local-vars
和with-bindings
都是使用相同的基本机制(pushThreadBindings
和popThreadBindings
)实现的,这表明他们应该有几乎相同的行为。
所以是的,你是对的,你不能指望在一个闭包中捕获的with-local-vars
值在with-local-vars
范围之外工作。但是,Clojure专门为构建这种类型的闭包提供了bound-fn
机制,捕获了所有当前的线程局部绑定:
(def foo (with-local-vars [bar 10] (fn [] @bar)))
(foo)
; => #object[clojure.lang.Var$Unbound 0x60063e12 "Unbound: #<Var: --unnamed-->"]
(def baz (with-local-vars [bar 10] (bound-fn [] @bar)))
(baz)
; => 10