Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by
edited by

I have been using the following function a lot:

 (defn set-var-root [v value]
   (alter-var-root v (constantly value)))

And I have seen this pattern a lot in other code too. It is like an idiom if I understand correctly.
Why is it not in clojure.core?

Might it be a good addition and if not, why not?

I have asked in clojurians slack and was pointed out to

(.bindRoot avar value)

Which I didn't know before also. But again the question why is it not part of the public API? Is there something wrong with using vars like this?

To give some context, I am developing a game engine and on app start I am setting global vars for input, graphics context, etc.


(defn- load-gdx-globals []
  (set-var-root #'gdl.app/app           Gdx/app)
  (set-var-root #'gdl.files/files       Gdx/files)
  (set-var-root #'gdl.graphics/graphics Gdx/graphics)
  (set-var-root #'gdl.input/input       Gdx/input))
I am using `.bindRoot` now, and can delete my custom function `set-var-root`.

I think that's the best approach.
Using the non-public, non-portable implementation api seems like the worst approach tbh.

1 Answer

+2 votes

As with all reference types, you should generally be creating new values by functionally applying a functional transformation to the old value (ie alter-var-root).

But really, because vars are global, you should prefer to use other mechanisms to hold state, either passing a stateful reference (like an atom) around, or in some relatively rare cases by putting a stateful reference in a var (but the fewer the better imo, ideally 0).

Yes, this is not in clojure.core because it is not something that you should be doing in general, as explained by this answer. State which changes after compilation really belongs in something protected like an atom, and the update semantics are a pure function which transforms the old state to the new state (which, for atoms, uses `swap!`).