kumarshantanu / promenade

Take program design oddities in stride with Clojure/ClojureScript
Eclipse Public License 1.0
106 stars 3 forks source link

print-method fails to dispatch #5

Closed shark8me closed 6 years ago

shark8me commented 6 years ago

Hi!

I've been using Promenade for some time, and find it quite useful, thanks for writing it :).

I've observed one issue (which isn't a bug, more like a repl-interface niggle).

(defn a
  []
  (prom/fail {:some :data}))

(prom/either->> (a))

gives

1. Unhandled java.lang.IllegalArgumentException
   Multiple methods in multimethod 'print-method' match dispatch value: class
   promenade.internal.Failure -> interface java.util.Map and interface
   clojure.lang.IDeref, and neither is preferred

              MultiFn.java:  178  clojure.lang.MultiFn/findAndCacheBestMethod
              MultiFn.java:  150  clojure.lang.MultiFn/getMethod
              MultiFn.java:  154  clojure.lang.MultiFn/getFn
              MultiFn.java:  233  clojure.lang.MultiFn/invoke
             pr_values.clj:   35  clojure.tools.nrepl.middleware.pr-values/pr-values/fn/reify
    interruptible_eval.clj:  113  clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn/fn
                  main.clj:  241  clojure.main/repl/read-eval-print
                  main.clj:  258  clojure.main/repl/fn
                  main.clj:  258  clojure.main/repl
                  main.clj:  174  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  646  clojure.core/apply
                  core.clj:  641  clojure.core/apply
                regrow.clj:   18  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  646  clojure.core/apply
                  core.clj: 1881  clojure.core/with-bindings*
                  core.clj: 1881  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   85  clojure.tools.nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   55  clojure.tools.nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  222  clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
    interruptible_eval.clj:  190  clojure.tools.nrepl.middleware.interruptible-eval/run-next/fn
                  AFn.java:   22  clojure.lang.AFn/run
   ThreadPoolExecutor.java: 1149  java.util.concurrent.ThreadPoolExecutor/runWorker
   ThreadPoolExecutor.java:  624  java.util.concurrent.ThreadPoolExecutor$Worker/run
               Thread.java:  748  java.lang.Thread/run

I'm using Spacemacs, and promenade version 0.5.0. Any suggestions why this isn't kicking in?

kumarshantanu commented 6 years ago

@shark8me There's probably something related to your project setup that's involving java.util.Map rather than persistent-map. Can you try running the following at the REPL before doing whatever that caused the error?

(import 'java.util.Map)
(import 'clojure.lang.IDeref)
(prefer-method print-method Map IDeref)
shark8me commented 6 years ago

@kumarshantanu

The error isn't seen if I run the imports you described. So what's the solution? Importing java.util.Map?

kumarshantanu commented 6 years ago

I think the issue can be fixed in promenade by preferring print-method for Map (instead of IPersistentMap) over IDeref. @shark8me Can you share a minimal example that can reproduce the issue?

kumarshantanu commented 6 years ago

@shark8me Alternatively, you can put an equivalent of this snippet in your project and execute at startup:

(import 'java.util.Map)
(import 'clojure.lang.IDeref)
(prefer-method print-method Map IDeref)
shark8me commented 6 years ago

by "minimal example", do you mean an entire project (along with the project.clj), or just the source. If it is just the source, then its :

(prom/fail {:some :a})

Sure, I can live with the workaround you suggested.

kumarshantanu commented 6 years ago

OK, I can reproduce the issue with Clojure 1.7.0 in the promenade repo as follows:

$ lein do clean, with-profile c17 repl
user=> (require '[promenade.core :as prom])
nil
user=> (prom/fail {:some :a})

IllegalArgumentException Multiple methods in multimethod 'print-method' match dispatch value: class promenade.internal.Failure -> interface java.util.Map and interface clojure.lang.IDeref, and neither is preferred  clojure.lang.MultiFn.findAndCacheBestMethod (MultiFn.java:178)

Thanks for reporting, @shark8me - will have a fix ready soon.

kumarshantanu commented 6 years ago

For posterity w.r.t. CLJS: https://stackoverflow.com/a/42917425/188505

kumarshantanu commented 6 years ago

@shark8me This issue is fixed in version 0.5.1 - thanks again!

shark8me commented 6 years ago

@kumarshantanu That works :). Thanks for the quick resolution! :+1: