5

有几篇有些旧的博客文章建议在混合动态变量时要小心binding, 和pmap,例如在这里,我们得到以下代码片段:

user=> (def *foo* 5)
#'user/*foo*
user=> (defn adder
             [param]
             (+ *foo* param))
#'user/adder
user=> (binding [*foo* 10]
         (doseq [v (pmap adder (repeat 3 5))]
           (println v)))
10
10
10
nil

但这不是我运行该代码时发生的情况(将第一行更改为(def ^:dynamic *foo* 5))。我得到了三个15s 作为输出(使用 Clojure 1.4),正如您天真地期望的那样——也就是说,传递给 pmap 的函数看到的绑定形式的变化。线程本地绑定和 pmap 交互的方式是否发生了变化?我在任何地方都找不到这个记录。

4

1 回答 1

5

从 1.3 开始,本地绑定集与函数一起发送到 pmap。因此,只要您标记 var ^:dynamic 这不再是问题。此功能称为Binding Conveyance,包含在 1.3 变更日志中:

来自:https ://github.com/clojure/clojure/blob/1.3.x/changes.txt

将工作传递给其他线程(例如 send、send-off、pmap、future)的 Clojure API 现在传达调用线程的动态绑定:

  (def ^:dynamic *num* 1)
  (绑定 [*num* 2] (future (println *num*)))
  ;; 打印“2”,而不是“1”
于 2012-08-24T21:36:59.080 回答