binding & pmap interaction change?

binding, clojure, dynamic-variables, pmap, thread-local

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"

Problem

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 `15`s 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.

Original source