There is no strict requirement for them: since you are observing correctly, you can do whatever you like without binding , and indeed, if binding does not exist, you can easily implement it relatively easily using macros and Java ThreadLocal s.
Binding, however, is useful as a way to pass a dynamic context into a function without having to explicitly pass a parameter.
This is especially useful when you compose deeply nested functions of a higher order and do not want to add additional parameters to each individual function in the call stack to pass some value to lower-level functions embedded deep inside.
To build on your example:
(def ^:dynamic *loud-noises* false) (defn speak [animal] (str (:name animal) " says " (let [sound (:sound animal)] (if *loud-noises* (.toUpperCase sound) sound)))) (speak dog) => "Dog says Woof" (binding [*loud-noises* true] (speak dog)) => "Dog says WOOF"
Note. I did not need to add an extra parameter to the speak function to get a different behavior. Adding an additional parameter would be trivial in this case, but imagine if the speak function was deeply immersed in a complex function of a higher order .....
However, I think the best advice overall is to avoid dynamic snapping if you really don't need it. It is usually best to add explicit parameters if you can: direct parameters simplify testing and talk about functions.
mikera
source share