【问题标题】:Clojure: binding vs. with-redefsClojure:绑定与 with-redefs
【发布时间】:2013-11-22 07:34:10
【问题描述】:

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

【问题讨论】:

标签: clojure dynamic-scope


【解决方案1】:

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 在生产代码中也很有用。
  • @Peeja 谢谢,换句话说,with-redefs 不应该在多线程上下文中使用?
  • @opqdonut 截至 2019 年 6 月,Vars 文档有一个 Binding conveyance 部分,其中突出显示 futuresendsend-offsend-offpmap 具有绑定传输的功能 - 确实这意味着不再需要binding-conveyor-fn
  • @ErikKaplun, binding-conveyor-fn 如果您使用您提到的功能,则不需要。但是,如果您使用(Thread. ...) 创建线程,您仍然需要它。
猜你喜欢
  • 1970-01-01
  • 2017-09-07
  • 2016-03-28
  • 2012-08-29
  • 2010-12-04
  • 1970-01-01
  • 2023-04-07
  • 2012-11-22
  • 2012-09-29
相关资源
最近更新 更多