Skip to content

Instantly share code, notes, and snippets.

@rwilson
Created March 21, 2016 23:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rwilson/34c88a97c6260a7dc703 to your computer and use it in GitHub Desktop.
Save rwilson/34c88a97c6260a7dc703 to your computer and use it in GitHub Desktop.
Multiple methods in multimethod match dispatch value
;; Happens sometimes when clojure.pprint/simple-dispatch or clojure.pprint/print-method
;; or whatnot don't have a stated preference for an object type that matches multiple
;; dispatch values. Here's a way around that.
;; Define a type that will match multiple dispatch values (IDeref & IPersistentMap)
user> (defrecord Foo [bar]
clojure.lang.IDeref
(deref [this]
(if bar
this
(assoc this :bar 1))))
user.Foo
;; Now, try to pprint an instance...
user> (clojure.pprint/pprint (map->Foo {}))
IllegalArgumentException Multiple methods in multimethod 'simple-dispatch' match dispatch value: class user.Foo -> interface clojure.lang.IDeref and interface clojure.lang.IPersistentMap, and neither is preferred clojure.lang.MultiFn.findAndCacheBestMethod (MultiFn.java:178)
;; That's the error we expected, so let's force it to print as a map
user> (defmethod clojure.pprint/simple-dispatch Foo [o]
((get-method clojure.pprint/simple-dispatch clojure.lang.IPersistentMap) o))
#object[clojure.lang.MultiFn 0x60f87fd7 "clojure.lang.MultiFn@60f87fd7"]
;; And try to print again
user> (pprint (map->Foo {}))
{:bar nil}
;; And print the deref'd version
user> (pprint @(map->Foo {}))
{:bar 1}
@simongray
Copy link

For anyone googling this, you can also simply do

(prefer-method print-method Foo Bar)
(prefer-method print-method Foo Baz)

... and so on for all of the cases where printing Foo conflicts with something else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment