我正试图重现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 (!)
事实上,我预计第三种情况将返回15,只要在单独的线程上执行添加,并且应该使用*dynamic-x*
的当前线程本地值(我认为它是10)。但是,出乎我意料的是,它居然返回了25。
我哪里错了?
future
的设计是将动态绑定传递给将来执行主体的其他线程(查看future
的源,它服从于future-call
,它使用一个名为binding-conveyor-fn
的函数,该函数显式复制线程本地绑定)。
这种IMO的动机是,当使用future
时,您希望在同一个"逻辑线程"中运行计算,但出于性能原因,实际上只有您在另一个Java线程中运行。
我同意它应该被明确地记录下来:)