Question

There are several somewhat old blog posts out there advising caution when mixing dynamic variables, binding, and pmap, e.g. here, where we get the following code snippet:

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

But that's not what happens when I run that code (changing the first line to (def ^:dynamic *foo* 5)). I get three 15s as output (using Clojure 1.4), just as you would naïvely expect—that is, with the change in the binding form seen by the function passed to pmap. Have the way thread-local bindings and pmap interact changed? I can't find this documented anywhere.

Était-ce utile?

La solution

starting in 1.3 the set of local bindings are sent to pmap along with the function. So as long as you mark the var ^:dynamic this is no longer a problem. This feature it called Binding Conveyance and is included in the 1.3 changelog:

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

Clojure APIs that pass work off to other threads (e.g. send, send-off, pmap, future) now convey the dynamic bindings of the calling thread:

  (def ^:dynamic *num* 1)
  (binding [*num* 2] (future (println *num*)))
  ;; prints "2", not "1"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top