Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reload a multimethod in Clojure REPL

Tags:

clojure

I am writing a multimethod in the REPL, functions can be redefined just fine, but if I redefine the dispatch function of a multi method it seems not to use the newly refined function:

;; simple fn to resolve defmethod to call, hardcoded to :do-it
(defn resolve-it [] :do-it)
(resolve-it) ;; :do-it, as expected

(defmulti do-something resolve-it)

(defmethod do-something :do-it [] (println "do-it"))
(defmethod do-something :oh-no [] (println "oh-no"))

(do-something) ;; "do-it", as expected

;; now change resolve-it
(defn resolve-it [] :oh-no)
(resolve-it) ;; :oh-no, as expected

(do-something) ;; "do-it", not as expected

(do-something) ;; "do-it", not expected

How do I get the mult imethod to reflect changes to the dispatch function, resolve-it?

like image 210
Kris Avatar asked Jun 28 '17 15:06

Kris


1 Answers

There is a simple technique that allows re-defining the dispatch function of the multimethod. The idea is to pass the var that holds the dispatch function to defmulti, not the function itself. Note the #'resolve-it in defmulti instead of just resolve-it. Thus the var is de-referenced at runtime, not just at compile time.

(defn resolve-it [] :do-it)
(resolve-it) ;; :do-it, as expected

(defmulti do-something #'resolve-it)

(defmethod do-something :do-it [] (println "do-it"))
(defmethod do-something :oh-no [] (println "oh-no"))

(do-something) ;; "do-it", as expected

;; now change resolve-it
(defn resolve-it [] :oh-no)
(resolve-it) ;; :oh-no, as expected

(do-something) ;; "oh-no", expected!!
like image 134
ez121sl Avatar answered Sep 21 '22 12:09

ez121sl