我正在尝试重现Chas描述的动态变量的陷阱 - http://cemerick.com/2009/11/03/be-mindful-of-clojures-binding/。
请考虑以下代码段:
(def ^:dynamic *dynamic-x* 10)
(defn adder [arg]
(+ *dynamic-x* arg))
(adder 5) ;; returns 15
(binding [*dynamic-x* 20]
(adder 5)) ;; returns 25
(binding [*dynamic-x* 20]
@(future (adder 5))) ;; returns 25 (!)
实际上,我希望第3个案例将返回15,只要在单独的线程上执行添加,并且应该使用当前线程本地值*dynamic-x*
(我应该是10)。但是,对我来说意外的是,它会返回25。
我哪里错了?
答案 0 :(得分:4)
future
的设计是将动态绑定传递给将在其中执行未来正文的其他线程(查看future
的来源,它遵循future-call
},它使用一个名为binding-conveyor-fn
的函数,它显式复制线程本地绑定)。
这个IMO的动机是当你使用future
想要在同一个“逻辑线程”中运行计算时,出于性能原因,只有你实际上是在另一个Java Thread中进行计算。
我同意它应该明确记录:)