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

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

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated: