Ben*_*itz 4 clojure thread-safety lazy-evaluation
(def ^:dynamic *d* 1)
(binding [*d* 2]
(println *d*)
(repeatedly 1 #(println *d*)))
Run Code Online (Sandbox Code Playgroud)
输出:
2
1
Run Code Online (Sandbox Code Playgroud)
为什么?为什么里面的函数repeatedly从外面看到动态var的值binding?
顺便说一句,我检查(.getId (java.lang.Thread/currentThread))了匿名函数的内部和外部:它是一样的.
创建的延迟序列repeatedly是从表单返回的,然后只有在通过REPL打印后才能实现,在绑定被"解开"之后,此时正在调用匿名函数.要查看是这种情况,请尝试以下两种变体:
(binding [*d* 2]
(println *d*)
(let [x (repeatedly 1 #(println *d*))]
(println (realized? x))
x))
Run Code Online (Sandbox Code Playgroud)
和
(binding [*d* 2]
(println *d*)
(doall (repeatedly 1 #(println *d*))))
Run Code Online (Sandbox Code Playgroud)
第二种变化迫使序列完全实现,同时仍在绑定范围内.
请注意,另一种强制解决问题的方法是使用以下方法"捕获"绑定bound-fn:
(binding [*d* 2]
(println *d*)
(repeatedly 1 (bound-fn [] (println *d*))))
Run Code Online (Sandbox Code Playgroud)