It seems to me that with-redefs
can do everything that binding
to a dynamic symbol can do, only it doesn't have the limitation of needing the ^:dynamic
metadata. So when should I use one over the other?
Aside from requiring the ^:dynamic
metadata, binding
also creates bindings that are only visible in the current thread, whereas the bindings made by with-redefs
are visible in all threads. So, with-redefs
is a very blunt tool and has the potential to affect other code running in the same VM. I've never seen with-redefs
used outside of test code, nor should it be (at least in my opinion).
I would summarize the difference between the two as thus:
Declaring a var as ^:dynamic
, together with the convention of using earmuffs to name dynamic vars (e.g. *my-dynamic-var*
), has the added bonus that it's a self-documenting way of advertising to callers that that part of your code can be modified dynamically.
In summary: prefer ^:dynamic and binding when writing APIs and production code. Use with-redefs in testing, and as a last resort to dynamically alter the behavior of vars beyond your control that weren't declared ^:dynamic
(and then, use with caution).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With