在Clojure中,变量是with-local-vars通过闭包来定义的吗?
考虑以下示例:
(defn foo []
(with-local-vars [bar 10]
(fn [] @bar)))
((foo))
Run Code Online (Sandbox Code Playgroud)
结果如下:
#object[clojure.lang.Var$Unbound 0x131f68d8 "Unbound: #<Var: --unnamed-->"]
Run Code Online (Sandbox Code Playgroud)
(相反,我期待得到10.)
Cf具有以下内容:
(defn foo []
(with-local-vars [bar 10] @bar))
(foo)
Run Code Online (Sandbox Code Playgroud)
结果:10.
基于文档,我不清楚,如果在Clojure中使用如上所述的本地变量是有效的,但我怀疑答案是否定的.你能否确认一下(或反驳,并解释我在第一个例子中做错了什么)?如果我的假设是明确的(即,本地变量不能用于闭包),那么解释原因是什么?
编辑:对于记录,这是我试图解决的问题.
这里的文档with-local-vars似乎不是特别清楚.它只是说它为变量创建了线程局部绑定,但没有说明退出with-local-vars作用域时它们发生了什么.
相反,with-bindings文档明确说明在离开该范围时会弹出线程局部绑定.
如果你看一下源代码,你可以看到,无论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
Run Code Online (Sandbox Code Playgroud)