【发布时间】:2013-11-22 07:34:10
【问题描述】:
clojure.core 有宏 bindings 和 with-redefs。查看 clojuredocs.org 上的文档字符串和示例,它们似乎做了非常相似的事情。有什么区别,我应该在什么情况下使用哪一个?
【问题讨论】:
标签: clojure dynamic-scope
clojure.core 有宏 bindings 和 with-redefs。查看 clojuredocs.org 上的文档字符串和示例,它们似乎做了非常相似的事情。有什么区别,我应该在什么情况下使用哪一个?
【问题讨论】:
标签: clojure dynamic-scope
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,]>
您可以使用(未记录的)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,]>
【讨论】:
with-redefs 用于测试(您可能想要进入并存根函数),binding 在生产代码中也很有用。
with-redefs 不应该在多线程上下文中使用?
future、send、send-off 和 send-off 和 pmap 具有绑定传输的功能 - 确实这意味着不再需要binding-conveyor-fn?
binding-conveyor-fn 如果您使用您提到的功能,则不需要。但是,如果您使用(Thread. ...) 创建线程,您仍然需要它。