How to reload multimethod in Clojure REPL

I am writing multimethod in REPL, the functions can be overridden just fine, but if I redefine the send function of the multithreaded method, it seems not to use the new 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 can I get mult imethod to reflect changes in the send function resolve-it,?

+4
source share
3 answers

There is a simple method that allows you to override the ellipsis submission function. The idea is to pass var, which contains the send function,, defmultirather than the function itself. Pay attention to #'resolve-itin defmultiinstead resolve-it. Thus, var is disabled at runtime, and 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!!
+8

clojuredocs exmaple defmulti . do-something (ns):

(ns-unmap *ns* 'do-something)

, :

(defmulti do-something resolve-it)
(defmethod do-something :do-it [] (println "do-it"))
(defmethod do-something :oh-no [] (println "oh-no"))
+3

, defmulti . , :

;; simple fn to resolve defmethod to call, hardcoded to :do-it
(defn who-is-it [person] (:name person))
(spyx (who-is-it {:name :joe}))

(defmulti  do-something who-is-it)
(defmethod do-something :homer [person] :doh)
(defmethod do-something :bill  [person] :oh-no)
(defmethod do-something :ted  [person] :excellent)

(spyx (do-something {:name :homer}))
(spyx (do-something {:name :bill}))

;; now change who-is-it
(defn who-is-it [arg] :ted)
(spyx (who-is-it :wilma)) ;; expected result = :excellent
(spyx (do-something {:name :betty}))

:

:reloading (tst.clj.core)
(who-is-it {:name :joe}) => :joe
(do-something {:name :homer}) => :doh
(do-something {:name :bill}) => :oh-no
(who-is-it :wilma) => :ted
:error-while-loading tst.clj.core

Error refreshing environment: java.lang.IllegalArgumentException: No method in multimethod 'do-something' for dispatch value: :betty, compiling:(tst/clj/core.clj:22:27)

, , , REPL, fn. do-something :

(defmulti  do-something who-is-it)
(defmethod do-something :homer [person] :doh)
(defmethod do-something :bill  [person] :oh-no)
(defmethod do-something :ted  [person] :excellent)

(spyx (do-something {:name :betty}))   ;=> ***same error ***
Error refreshing environment: java.lang.IllegalArgumentException: No method in multimethod 'do-something' for dispatch value: :betty, compiling:(tst/clj/core.clj:30:1)

:

;; simple fn to resolve defmethod to call, hardcoded to :do-it
(defn who-is-it [person] (:name person))
(spyx (who-is-it {:name :joe}))

;; now change who-is-it
(defn who-is-it [arg] :ted)
(spyx (who-is-it :wilma)) ;; expected result = :ted
; (spyx (do-something {:name :betty}))

(defmulti  do-something who-is-it)
(defmethod do-something :homer [person] :doh)
(defmethod do-something :bill  [person] :oh-no)
(defmethod do-something :ted  [person] :excellent)

(dotest
  (spyx (do-something {:name :betty})))

(do-something {:name :betty}) => :excellent  ; *** as expected ***

Update

ns-unmap, Rumid, . , defmulti defmethod:

(ns-unmap *ns* 'do-something)    ; be sure to remember the quote
(defmulti  do-something who-is-it)
(defmethod do-something :homer [person] :doh)
(defmethod do-something :bill  [person] :oh-no)
(defmethod do-something :ted  [person] :excellent)

(dotest
  (newline)
  (spyx (do-something {:name :betty}))) ;=> :excellent
+1

Source: https://habr.com/ru/post/1680337/


All Articles