Clojure with-local-vars关闭

Att*_*lio 2 closures clojure

在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中使用如上所述的本地变量是有效的,但我怀疑答案是否定的.你能否确认一下(或反驳,并解释我在第一个例子中做错了什么)?如果我的假设是明确的(即,本地变量不能用于闭包),那么解释原因是什么?

编辑:对于记录,这是我试图解决的问题.

Dao*_*Wen 6

这里的文档with-local-vars似乎不是特别清楚.它只是说它为变量创建了线程局部绑定,但没有说明退出with-local-vars作用域时它们发生了什么.

相反,with-bindings文档明确说明在离开该范围时会弹出线程局部绑定.

如果你看一下源代码,你可以看到,无论with-local-varswith-bindings使用实现了相同的基本机制(pushThreadBindingspopThreadBindings),这表明他们应该有几乎相同的行为.

所以是的,你是对的,你不能指望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)