Clojure: binding vs. with-redefs
Asked Answered
N

1

32

clojure.core has the macros bindings and with-redefs. Looking at the docstrings and the examples on clojuredocs.org, they seem to do something very similar. What is the difference and which one should I use in which situations?

Nourish answered 22/11, 2013 at 7:34 Comment(1)
Also see this question: #15748274Aniela
A
36

Clojure Vars can have thread-local bindings. binding uses these, while with-redefs actually alters the root binding (which is someting like the default value) of the var.

Another difference is that binding only works for :dynamic vars while with-redefs works for all vars.

Examples:

user=> (def ^:dynamic *a* 1)
#'user/*a*
user=> (binding [*a* 2] *a*)
2
user=> (with-redefs [*a* 2] *a*)
2
user=> (binding [*a* 2] (doto (Thread. (fn [] (println "*a* is " *a*))) (.start) (.join)))
*a* is  1
#<Thread Thread[Thread-2,5,]>
user=> (with-redefs [*a* 2] (doto (Thread. (fn [] (println "*a* is " *a*))) (.start) (.join)))
*a* is  2
#<Thread Thread[Thread-3,5,]>

You can use the (undocumented) binding-conveyor-fn to convey thread-local bindings into new threads:

user=> (binding [*a* 2] (doto (Thread. (#'clojure.core/binding-conveyor-fn (fn [] (println "*a* is " *a*)))) (.start) (.join)))
*a* is  2
#<Thread Thread[Thread-5,5,]>
Allveta answered 22/11, 2013 at 7:41 Comment(4)
All of which is why with-redefs is meant for use in tests (where you may want to reach in and stub out a function), which binding can be useful in production code as well.Touchwood
@Touchwood thanks, so in other words, with-redefs should never be used in multi-threaded contexts?Overseas
@Allveta as of 2019 june, the Vars documentation has a Binding conveyance section which highlights future, send, send-off and pmap as having the capabilities for binding conveyance — does it mean that binding-conveyor-fn is no longer needed?Overseas
@ErikKaplun, binding-conveyor-fn is not needed if you use the functions you mentioned. However, if you create threads with (Thread. ...), you still need it.Nourish

© 2022 - 2024 — McMap. All rights reserved.