What is the difference between def and defonce in Clojure?
Asked Answered
B

3

26

What is the difference between def and defonce in Clojure?

When to use def over defonce or vice versa?

Ball answered 20/5, 2016 at 12:39 Comment(0)
M
36

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
Mhd answered 20/5, 2016 at 12:48 Comment(0)
G
8

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 )))
Gerstner answered 20/5, 2016 at 12:53 Comment(0)
C
1

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.

Copyhold answered 10/2, 2022 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.