为什么动态绑定会影响未来的身体?

Ole*_*Cat 4 future clojure dynamic-variables

我正在尝试重现 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 (!)
Run Code Online (Sandbox Code Playgroud)

实际上,我期望一旦在单独的线程上执行添加并且*dynamic-x*应该使用当前线程本地值(我应该是 10),第三种情况将返回 15。但是,出乎我意料的是,它返回了 25。

我哪里错了?

Val*_*nck 5

它的设计是future将动态绑定传递给将在其中执行未来主体的其他线程(查看 的源代码future,它遵循future-call,它使用一个名为 的函数binding-conveyor-fn来显式复制线程本地绑定)。

这个 IMO 的动机是,当使用时,future您希望在同一个“逻辑线程”中运行计算,但出于性能原因,您实际上是在另一个 Java 线程中执行它。

我同意它应该被明确记录:)