Clojure with-local-vars关闭

时间:2017-02-04 13:09:39

标签: clojure closures

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

编辑:记录this is the problem I was trying to solve

1 个答案:

答案 0 :(得分:6)

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

相比之下,with-bindings documentation明确表示在离开该范围时会弹出线程局部绑定。

如果您查看源代码,可以看到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