Clojure:绑定与with-redefs

Mii*_*kka 27 clojure dynamic-scope

clojure.core具有宏绑定with-redefs.看看关于clojuredocs.org的文档字符串和示例,它们似乎做了非常相似的事情.有什么区别,我应该在哪些情况下使用哪一个?

opq*_*nut 30

Clojure Vars可以有线程局部绑定.binding使用这些,with-redefs实际上改变了var的根绑定(有点像默认值).

另一个区别是,binding只对:dynamic增值经销商,同时with-redefs对所有瓦尔作品.

例子:

user=> (def ^:dynamic *a* 1)
#'user/*a*
user=> (binding [*a* 2] *a*)
2
user=> (with-redefs [*a* 2] *a*)
2
user=> (binding [*a* 2] (doto (Thread. (fn [] (println "*a* is " *a*))) (.start) (.join)))
*a* is  1
#<Thread Thread[Thread-2,5,]>
user=> (with-redefs [*a* 2] (doto (Thread. (fn [] (println "*a* is " *a*))) (.start) (.join)))
*a* is  2
#<Thread Thread[Thread-3,5,]>
Run Code Online (Sandbox Code Playgroud)

您可以使用(未​​记录的)binding-conveyor-fn将线程本地绑定传递到新线程:

user=> (binding [*a* 2] (doto (Thread. (#'clojure.core/binding-conveyor-fn (fn [] (println "*a* is " *a*)))) (.start) (.join)))
*a* is  2
#<Thread Thread[Thread-5,5,]>
Run Code Online (Sandbox Code Playgroud)

  • 所有这些都是为什么`with-redefs`意味着在测试中使用(你可能想要进入并存根函数),"绑定"在生产代码中也很有用. (5认同)