What is the difference between def and defonce in Clojure?
When to use def over defonce or vice versa?
What is the difference between def and defonce in Clojure?
When to use def over defonce or vice versa?
defonce
is skipped when variable is already defined.
user> (def a 1) ;;=> #'user/a
user> a ;;=> 1
user> (def a 2) ;;=> #'user/a
user> a ;;=> 2
user> (defonce b 1) ;;=> #'user/b
user> b ;;=> 1
user> (defonce b 2) ;;=> nil
user> b ;;=> 1
Defonce only binds the name to the root value if the name has no root value.
For example, like Jay Fields blogs about, it can be used in conjunction when you want to reload namespaces but you might not need to reload all.
(defonce ignored-namespaces (atom #{}))
(defn reload-all []
(doseq [n (remove (comp @ignored-namespaces ns-name) (all-ns))]
(require (ns-name n) :reload )))
As for when to use defonce
, if you're using system with hot reloading (CLJS with mount and re-frame for example), defonce
is useful to keep the state between reloads.
Similar situation when you re-evaluate source file yourself (e.g. in REPL) but want to keep the value of the var bound to the symbol.
© 2022 - 2024 — McMap. All rights reserved.