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.)

+3


source to share


2 answers


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.



+3


source


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.

+1


source







All Articles