Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mixed string and keyword dispatch values break pprint pretty-printer #151

Open
vkz opened this issue Aug 21, 2024 · 2 comments
Open

Mixed string and keyword dispatch values break pprint pretty-printer #151

vkz opened this issue Aug 21, 2024 · 2 comments

Comments

@vkz
Copy link

vkz commented Aug 21, 2024

Hi @camsaul appears mixing dispatch values like in the following examples break the default pretty-printer pprint. Typically, this shouldn't be a problem except when you store a multimethod in some compound data you pass around - like state of a finite state machine or something. The moment REPL attempts to pretty print such a value it'll throw an exception. Maybe related to problem with sort you mention in another issue.

Version: methodical/methodical {:mvn/version "1.0.111"}

To reproduce, try any of these:

Examples 1:

(defmulti boom (fn [arg] arg))
(defmethod boom :bar [_] :bar)
(pprint boom)
;; => works fine
(defmethod boom "bar" [_] "bar")
(pprint boom)
;; => with this method added throws
stacktrace
1. Unhandled java.lang.ClassCastException
   class clojure.lang.Keyword cannot be cast to class java.lang.String
   (clojure.lang.Keyword is in unnamed module of loader 'app';
   java.lang.String is in module java.base of loader 'bootstrap')

               String.java:  140  java.lang.String/compareTo
                 Util.java:  153  clojure.lang.Util/compare
    APersistentVector.java:  442  clojure.lang.APersistentVector/compareTo
                 Util.java:  153  clojure.lang.Util/compare
                  core.clj:  842  clojure.core/compare
                  core.clj:  833  clojure.core/compare
            AFunction.java:   51  clojure.lang.AFunction/compare
              TimSort.java:  355  java.util.TimSort/countRunAndMakeAscending
              TimSort.java:  220  java.util.TimSort/sort
               Arrays.java: 1233  java.util.Arrays/sort
                  core.clj: 3117  clojure.core/sort
                  core.clj: 3104  clojure.core/sort
                  core.clj: 3104  clojure.core/sort
              standard.clj:   20  methodical.impl.method-table.standard/dispatch-value-map
              standard.clj:   15  methodical.impl.method-table.standard/dispatch-value-map
              standard.clj:   34  methodical.impl.method-table.standard.StandardMethodTable/pretty
                  core.clj:   41  pretty.core/eval17673/fn
              MultiFn.java:  229  clojure.lang.MultiFn/invoke
           pprint_base.clj:  194  clojure.pprint/write-out
              dispatch.clj:   79  clojure.pprint/pprint-simple-list/fn
              dispatch.clj:   78  clojure.pprint/pprint-simple-list
              dispatch.clj:   88  clojure.pprint/pprint-list
              dispatch.clj:   87  clojure.pprint/pprint-list
              MultiFn.java:  229  clojure.lang.MultiFn/invoke
           pprint_base.clj:  194  clojure.pprint/write-out
           pprint_base.clj:  171  clojure.pprint/write-out
                  core.clj:   41  pretty.core/eval17673/fn
              MultiFn.java:  229  clojure.lang.MultiFn/invoke
           pprint_base.clj:  194  clojure.pprint/write-out
              dispatch.clj:   79  clojure.pprint/pprint-simple-list/fn
              dispatch.clj:   78  clojure.pprint/pprint-simple-list
              dispatch.clj:   88  clojure.pprint/pprint-list
              dispatch.clj:   87  clojure.pprint/pprint-list
              MultiFn.java:  229  clojure.lang.MultiFn/invoke
           pprint_base.clj:  194  clojure.pprint/write-out
           pprint_base.clj:  171  clojure.pprint/write-out
                  core.clj:   41  pretty.core/eval17673/fn
              MultiFn.java:  229  clojure.lang.MultiFn/invoke
           pprint_base.clj:  194  clojure.pprint/write-out
              dispatch.clj:   79  clojure.pprint/pprint-simple-list/fn
              dispatch.clj:   78  clojure.pprint/pprint-simple-list
              dispatch.clj:   88  clojure.pprint/pprint-list
              dispatch.clj:   87  clojure.pprint/pprint-list
              MultiFn.java:  229  clojure.lang.MultiFn/invoke
           pprint_base.clj:  194  clojure.pprint/write-out
           pprint_base.clj:  171  clojure.pprint/write-out
                  core.clj:   41  pretty.core/eval17673/fn
              MultiFn.java:  229  clojure.lang.MultiFn/invoke
           pprint_base.clj:  194  clojure.pprint/write-out
           pprint_base.clj:  249  clojure.pprint/pprint/fn
           pprint_base.clj:  248  clojure.pprint/pprint
           pprint_base.clj:  241  clojure.pprint/pprint
           pprint_base.clj:  245  clojure.pprint/pprint
           pprint_base.clj:  241  clojure.pprint/pprint

Example 2

(defmulti bam (fn [arg] arg))
(defmethod bam [:bar] [_] :bar)
(pprint bam)
;; => works fine
(defmethod bam ["bar"] [_] "bar")
(pprint bam)
;; => with this method added throws

Example 3

(defmulti foo first)
(defmethod foo "bar" [_] 42)
(defmethod foo ["bar"] [_] 42)
(pprint foo)

(defmulti baz first)
(defmethod baz :bar [_] 42)
(defmethod baz [:bar] [_] 42)
(pprint baz)
@vkz
Copy link
Author

vkz commented Aug 21, 2024

Def sort related: throws attempting to sort primaries so, yeah, likely related to #140

For now and as a temp hack I dropped sort and altered var root:

(defn- dispatch-value-map
  "Create a representation of `primary` and `aux` methods using their dispatch values for pretty-printing a method table."
  [primary aux]
  (not-empty
   (merge
    (when-let [dvs (not-empty (vec  #_removed_sort_here (keys primary)))]
      {:primary dvs})
    (when-let [aux-methods (not-empty
                            (into {} (for [[qualifier dv->fns] aux
                                           :let                [dvs (for [[dv fns] dv->fns
                                                                          _f       fns]
                                                                      dv)]
                                           :when               (seq dvs)]
                                       [qualifier (vec (sort dvs))])))]
      {:aux aux-methods}))))

(alter-var-root
 (var methodical.impl.method-table.standard/dispatch-value-map)
 (fn [_f]
   dispatch-value-map))

ugly but does the trick.

@camsaul
Copy link
Owner

camsaul commented Aug 30, 2024

Hi @vkz, would you be interested in submitting a PR for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants