How to avoid defmulti being defonce with the REPL session?

macros

#1

(note: using Cider)
I use defmulti and defmethod in my code, eval-buffer, and test them. They have an error, so I rewrite them (change them to receive a map instead of sequential args). However, eval-buffer won’t update the definition; only restarting the repl session seems to capture my changes. Is there a way to cause macros like defmulti to reload without restarting my repl?


#2

defmulti defaults to defonce semantics. Add a def before the defmulti declaration to get def semantics instead:

(def foo nil)
(defmulti foo (fn [n m] n))
(defmethod foo :default [n m] (prn [:n n]))

#3

Does this work with all macros?


#4

defmulti is indeed a macro but so far as I can see whether or not it’s implemented as a macro is not relevant to its reevaluation behavior.


#5

Indeed, defmulti does this because otherwise reevaluating the defmulti would invalidate all the corresponding defmethods.


#6

Oh, interesting. I always thought it was an issue because of class generation. I’m not sure I totally follow the logic, like, what scenario would it be a problem? Since namespaces are loaded once only anyways.


#7

Perhaps https://github.com/clojure/tools.namespace#reloading-code-motivation could help? It mentions defmulti so I suppose it works with that.


#8

What about clojurescript where everything is reloaded when a file changes? Any tips on handling this? I vaguely remember seeing something like:

(def cool-multi nil)
(defmethod cool-multi ,,,)

But I’m not sure if that was the right thing to do or not.