Question

I was reading the clojure page on vars (here: https://clojure.org/reference/vars) which states that when a var is marked dynamic binding is thread local:

By default Vars are static, but per-thread bindings for Vars defined with metadata mark them as dynamic can be established via the macro binding and within-thread they obey a stack discipline

And a bit later:

Bindings created with binding cannot be seen by any other thread. Likewise, bindings created with binding can be assigned to, which provides a means for a nested context to communicate with code before it on the call stack. This capability is opt-in only by setting a metadata tag :dynamic to true as in the code block above.

So I decided to try this out:

(def ^:dynamic x 0)
(defn print-x [] (prn x))
(binding [x 100] @(future (print-x)))

And I expect to see 0 printed because future causes the operation to execute in a new thread, but the result I get is 100. I also noticed that the binding documentation does not make any mention of thread local binding, whereas there's a with-bindings function (or macro) which does talk about thread local bindings and has an alternate (wonky, if you ask me) syntax for specifying bindings, but that doesn't do what I expect either.

Any ideas? I must be missing something obvious.

Was it helpful?

Solution

The future function will automatically convey its bindings to the remote thread. This happens with the binding-conveyor-fn, which is similar to bound-fn which you can use for the same purpose in your own code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top