Best Practice for globals in clojure, (refs vs alter-var-root)?

Jeremy Wall picture Jeremy Wall · Jul 16, 2010 · Viewed 10.6k times · Source

I've found myself using the following idiom lately in clojure code.

(def *some-global-var* (ref {}))

(defn get-global-var []
  @*global-var*)

(defn update-global-var [val]
  (dosync (ref-set *global-var* val)))

Most of the time this isn't even multi-threaded code that might need the transactional semantics that refs give you. It just feels like refs are for more than threaded code but basically for any global that requires immutability. Is there a better practice for this? I could try to refactor the code to just use binding or let but that can get particularly tricky for some applications.

Answer

mikera picture mikera · Jul 16, 2010

I always use an atom rather than a ref when I see this kind of pattern - if you don't need transactions, just a shared mutable storage location, then atoms seem to be the way to go.

e.g. for a mutable map of key/value pairs I would use:

(def state (atom {}))

(defn get-state [key]
  (@state key))

(defn update-state [key val]
  (swap! state assoc key val))