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.