Clojure

Print multi method dispatch values in the exception messages.

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Trivial Trivial
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Patch:
    Code and Test

Description

The error messages of defmulti are at the moment not as helpful as they could be under certain circumstances. Calling this multi method with a lazy seq as it's dispatch argument raises the following exception:

(defmulti test-multi identity)
(defmethod test-multi 1 [arg] true)

(test-multi (map identity [:x]))
;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187

Sometimes it would be useful to actually see which values are in the lazy seq being dispatched on. A better error message could look like
this for example:

(test-multi (map identity [:x]))
;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq

This patch addresses this issue by formatting the dispatch value via `pr-str` and printing the class before it is passed to the exception constructor. The same is also done for the methods in MultiFn.java that throw a dispatch value as part of their exception message.

Activity

Roman Scherer made changes -
Field Original Value New Value
Attachment pr-str-dispatch-value.diff [ 12907 ]
Roman Scherer made changes -
Description The error messages of defmulti are at the moment not as helpful as
they could be under certain circumstances.

Having this definition of a simple multi method.

    (defmulti test-multi identity)

    (defmethod test-multi 1 [arg]
      true)

Calling this multi method with a lazy seq as it's dispatch argument
raises the following exception:

    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod
    ;=> 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187

Sometimes it would be useful to actually see which values are in the
lazy seq being dispatched on. A better error message could look like
this for example:

    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod
    ;=> 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq

This patch addresses this issue by formatting the dispatch value via
`pr-str` and printing the class before it is passed to the exception
constructor. The same is also done for the methods in MultiFn.java
The error messages of defmulti are at the moment not as helpful as
they could be under certain circumstances.

Having this definition of a simple multi method.

    (defmulti test-multi identity)

    (defmethod test-multi 1 [arg]
      true)

Calling this multi method with a lazy seq as it's dispatch argument
raises the following exception:

    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187

Sometimes it would be useful to actually see which values are in the
lazy seq being dispatched on. A better error message could look like
this for example:

    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq

This patch addresses this issue by formatting the dispatch value via
`pr-str` and printing the class before it is passed to the exception
constructor. The same is also done for the methods in MultiFn.java
that throw a dispatch value as part of their exception message.
Roman Scherer made changes -
Patch Code [ 10001 ]
Alex Miller made changes -
Description The error messages of defmulti are at the moment not as helpful as
they could be under certain circumstances.

Having this definition of a simple multi method.

    (defmulti test-multi identity)

    (defmethod test-multi 1 [arg]
      true)

Calling this multi method with a lazy seq as it's dispatch argument
raises the following exception:

    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187

Sometimes it would be useful to actually see which values are in the
lazy seq being dispatched on. A better error message could look like
this for example:

    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq

This patch addresses this issue by formatting the dispatch value via
`pr-str` and printing the class before it is passed to the exception
constructor. The same is also done for the methods in MultiFn.java
that throw a dispatch value as part of their exception message.
The error messages of defmulti are at the moment not as helpful as
they could be under certain circumstances.

Having this definition of a simple multi method.

{code}
    (defmulti test-multi identity)
    (defmethod test-multi 1 [arg] true)
{code}

Calling this multi method with a lazy seq as it's dispatch argument
raises the following exception:

{code}
    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187
{code}

Sometimes it would be useful to actually see which values are in the
lazy seq being dispatched on. A better error message could look like
this for example:

{code}
    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq
{code}

This patch addresses this issue by formatting the dispatch value via
`pr-str` and printing the class before it is passed to the exception
constructor. The same is also done for the methods in MultiFn.java
that throw a dispatch value as part of their exception message.
Labels errormsgs
Alex Miller made changes -
Description The error messages of defmulti are at the moment not as helpful as
they could be under certain circumstances.

Having this definition of a simple multi method.

{code}
    (defmulti test-multi identity)
    (defmethod test-multi 1 [arg] true)
{code}

Calling this multi method with a lazy seq as it's dispatch argument
raises the following exception:

{code}
    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187
{code}

Sometimes it would be useful to actually see which values are in the
lazy seq being dispatched on. A better error message could look like
this for example:

{code}
    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq
{code}

This patch addresses this issue by formatting the dispatch value via
`pr-str` and printing the class before it is passed to the exception
constructor. The same is also done for the methods in MultiFn.java
that throw a dispatch value as part of their exception message.
The error messages of defmulti are at the moment not as helpful as they could be under certain circumstances. Calling this multi method with a lazy seq as it's dispatch argument raises the following exception:

{code}
    (defmulti test-multi identity)
    (defmethod test-multi 1 [arg] true)
    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187
{code}

Sometimes it would be useful to actually see which values are in the lazy seq being dispatched on. A better error message could look like
this for example:

{code}
    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq
{code}

This patch addresses this issue by formatting the dispatch value via `pr-str` and printing the class before it is passed to the exception constructor. The same is also done for the methods in MultiFn.java that throw a dispatch value as part of their exception message.
Hide
Nicola Mometto added a comment -

What if the value is infinite lazy-seq?

Show
Nicola Mometto added a comment - What if the value is infinite lazy-seq?
Hide
Roman Scherer added a comment -

Nicola, I forgot those. But I think infinite sequences could be handled with:

(set! *print-length* 10)

I'll try it out and will update the patch later.

Any other edge cases in mind?

Show
Roman Scherer added a comment - Nicola, I forgot those. But I think infinite sequences could be handled with:
(set! *print-length* 10)
I'll try it out and will update the patch later. Any other edge cases in mind?
Hide
Roman Scherer added a comment -

After having read "Controlling run-away trains, onions, and exercise
bikes" [1] I now bind print-length and print-size when building
the error message. This helps when not being able to dispatch on this
for example:

(test-multi (let [x (atom 0)] (reset! x {:deeper x})))

However I'm not sure if this helps in the following case, where
dispatching would fail on an infinite seq.

(test-multi (iterate inc 0))

The above doesn't terminate in Clojure 1.6.0, nor does it when binding
print-length like the attached patch does.

[1] http://blog.n01se.net/blog-n01se-net-p-85.html

Show
Roman Scherer added a comment - After having read "Controlling run-away trains, onions, and exercise bikes" [1] I now bind print-length and print-size when building the error message. This helps when not being able to dispatch on this for example:
(test-multi (let [x (atom 0)] (reset! x {:deeper x})))
However I'm not sure if this helps in the following case, where dispatching would fail on an infinite seq.
(test-multi (iterate inc 0))
The above doesn't terminate in Clojure 1.6.0, nor does it when binding print-length like the attached patch does. [1] http://blog.n01se.net/blog-n01se-net-p-85.html
Roman Scherer made changes -
Attachment pr-str-dispatch-value-safe.diff [ 12908 ]
Roman Scherer made changes -
Patch Code [ 10001 ] Code and Test [ 10002 ]
Roman Scherer made changes -
Attachment pr-str-dispatch-value.diff [ 12907 ]
Roman Scherer made changes -
Description The error messages of defmulti are at the moment not as helpful as they could be under certain circumstances. Calling this multi method with a lazy seq as it's dispatch argument raises the following exception:

{code}
    (defmulti test-multi identity)
    (defmethod test-multi 1 [arg] true)
    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187
{code}

Sometimes it would be useful to actually see which values are in the lazy seq being dispatched on. A better error message could look like
this for example:

{code}
    (test-multi (map identity [:x]))
    ;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq
{code}

This patch addresses this issue by formatting the dispatch value via `pr-str` and printing the class before it is passed to the exception constructor. The same is also done for the methods in MultiFn.java that throw a dispatch value as part of their exception message.
The error messages of defmulti are at the moment not as helpful as they could be under certain circumstances. Calling this multi method with a lazy seq as it's dispatch argument raises the following exception:

{code}
(defmulti test-multi identity)
(defmethod test-multi 1 [arg] true)
(test-multi (map identity [:x]))
;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187
{code}

Sometimes it would be useful to actually see which values are in the lazy seq being dispatched on. A better error message could look like
this for example:

{code}
(test-multi (map identity [:x]))
;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq
{code}

This patch addresses this issue by formatting the dispatch value via `pr-str` and printing the class before it is passed to the exception constructor. The same is also done for the methods in MultiFn.java that throw a dispatch value as part of their exception message.
Roman Scherer made changes -
Description The error messages of defmulti are at the moment not as helpful as they could be under certain circumstances. Calling this multi method with a lazy seq as it's dispatch argument raises the following exception:

{code}
(defmulti test-multi identity)
(defmethod test-multi 1 [arg] true)
(test-multi (map identity [:x]))
;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187
{code}

Sometimes it would be useful to actually see which values are in the lazy seq being dispatched on. A better error message could look like
this for example:

{code}
(test-multi (map identity [:x]))
;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq
{code}

This patch addresses this issue by formatting the dispatch value via `pr-str` and printing the class before it is passed to the exception constructor. The same is also done for the methods in MultiFn.java that throw a dispatch value as part of their exception message.
The error messages of defmulti are at the moment not as helpful as they could be under certain circumstances. Calling this multi method with a lazy seq as it's dispatch argument raises the following exception:

{code}
(defmulti test-multi identity)
(defmethod test-multi 1 [arg] true)

(test-multi (map identity [:x]))
;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value: clojure.lang.LazySeq@3c6f1187
{code}

Sometimes it would be useful to actually see which values are in the lazy seq being dispatched on. A better error message could look like
this for example:

{code}
(test-multi (map identity [:x]))
;=> java.lang.IllegalArgumentException: No method in multimethod 'test-multi' for dispatch value (:x) of class clojure.lang.LazySeq
{code}

This patch addresses this issue by formatting the dispatch value via `pr-str` and printing the class before it is passed to the exception constructor. The same is also done for the methods in MultiFn.java that throw a dispatch value as part of their exception message.

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated: