What are the dangers or disadvantages of overriding variables?
I always load the namespace not-really-constants
. It contains, among other definitions:
(def foo 0.05)
Another namespace contains
(ns other-ns
(require [not-really-constants :as cn]))
(defn bar [x] (* x cn/foo))
However, sometimes I want it to foo
have a different meaning. So I am loading a namespace containing
(in-ns 'not-really-constants)
(def foo 0.025)
And then I call other-ns/bar
at the place where it is usually called. bar
then uses the new value foo
, 0.025, rather than the original 0.05.
I'm not sure if this behavior should be surprised. I think of overriding with def
as a convenience in repl, but as something that cannot be done in normal code. However, I don't know why. Overriding foo
this way seems to work without issue, running everything from the command line with lein run
, uploading files via require
.
So my question is, what are the dangers or other disadvantages of this practice - i.e. overriding a variable with def
?
(BTW I am not adding ^:dynamic
to the definition foo
because I do not need thread-local bindings, the new value foo
should be used everywhere. If I add ^:const
to the definition foo
, it bar
uses the original value 0.05, even though I overridden foo
as I bar
should in this case.)
source to share
Overriding var is not thread safe and should not be done in production environments. There is a good response to a similar question that goes deeper for main reasons.
source to share
The main disadvantage of overriding vars in Clojure has less to do with thread safety and more to do with the inherent dangers of mutable state. Idiomatic Clojure strives to be purely functional and free of side effects. This makes it much easier to reason about the logic of your program - given the same inputs, the function will always produce the same output.
When you override var, you basically think of it as a mutable global variable. Now the behavior of code using this variable depends not only on its inputs, but also on the order in which it is executed in relation to other code that might change this variable. This extra dimension of time makes your program much more complex.
I would consider overriding var as a code smell: in this particular situation it might be fine, but it should be a sign that you should reevaluate your approach and see if there is a better way.
source to share