Share your thoughts in the 2024 State of Clojure Survey!

Welcome! Please see the About page for a little more info on how this works.

0 votes
in Errors by

The following broken code:

(let [[x y] {}] x)

provides the following stack trace:

`
Exception in thread "main" java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap (test.clj:0)

    at clojure.lang.Compiler.eval(Compiler.java:4543)
    at clojure.lang.Compiler.load(Compiler.java:4857)
    at clojure.lang.Compiler.loadFile(Compiler.java:4824)
    at clojure.main$load_script__5833.invoke(main.clj:206)
    at clojure.main$script_opt__5864.invoke(main.clj:258)
    at clojure.main$main__5888.doInvoke(main.clj:333)
    at clojure.lang.RestFn.invoke(RestFn.java:413)
    at clojure.lang.Var.invoke(Var.java:346)
    at clojure.lang.AFn.applyToHelper(AFn.java:173)
    at clojure.lang.Var.applyTo(Var.java:463)
    at clojure.main.main(main.java:39)

Caused by: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap

    at clojure.lang.RT.nth(RT.java:800)
    at clojure.core$nth__3578.invoke(core.clj:873)
    at user$eval__1.invoke(test.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:4532)
    ... 10 more

`

The message "nth not supported on this type" while correct doesn't make the cause of the error very clear. Better error messages when destructuring would be very helpful.

10 Answers

0 votes
by

Comment made by: importer

Converted from http://www.assembla.com/spaces/clojure/tickets/5

0 votes
by

Comment made by: ekoontz

Please see the attached patch which produces a (hopefully more clear) error message as shown below (given the broken code shown in the original bug report):

Clojure 1.4.0-master-SNAPSHOT user=> (let [x 42 y 43] (+ x y)) 85 user=> (let [[x y] {}] x) UnsupportedOperationException left side of binding must be a symbol (found a PersistentVector instead). clojure.lang.Compiler.checkLet (Compiler.java:6545) user=>

In addition, this patch checks the argument of (let) as shown below:

user=> (let 42) UnsupportedOperationException argument to (let) must be a vector (found a Long instead). clojure.lang.Compiler.checkLet (Compiler.java:6553)

0 votes
by

Comment made by: ekoontz

Patch produced by doing git diff against commit ba930d95fc (master branch).

0 votes
by

Comment made by: ekoontz

Sorry, this patch is wrong: it assumes that the left side of the binding is wrong - the {{[x y]}} in :

(let [[x y] {}] x)

because {{[x y]}} is a vector, when in fact, the left side is fine (per http://clojure.org/special_forms#let : "Clojure supports abstract structural binding, often called destructuring, in let binding lists".)

So it's the right side (the {}) that needs to be checked and flagged as erroneous, not the {{[x y]}}.

0 votes
by

Comment made by: carinmeier

Add patch better-error-for-let-vector-map-binding

This produces the following:

(let [[x y] {}] x) Exception map binding to vector is not supported

There are other cases that are not handled by this though --- like binding vector to a set

user=> (let [[x y] #{}] x) UnsupportedOperationException nth not supported on this type: PersistentHashSet

Wondering if it might be better to try convert the map to a seq to support? Although this might be another issue.

Thoughts?

0 votes
by

Comment made by: aaron

This seems too specific. Is this issue indicative of a larger problem that should be addressed? Even if this is the only case where bindings produce poor error messages, all the cases described above should be addressed in the patch.

0 votes
by

Comment made by: carinmeier

Unfortunately, realized that this still does not cover the nested destructuring cases. Coming to the conclusion, that my approach above is not going to work for this.

0 votes
by

Comment made by: carinmeier

File: clj-5-destructure-error.diff

Added support for nested destructuring errors

let [[[x1 y1][x2 y2]] [[1 2] {}]] ;=> UnsupportedOperationException let cannot destructure class clojure.lang.PersistentArrayMap.

0 votes
by

Comment made by: hiredman

I am not wild about that error message, let can destructure a map fine.

If there error message were to change, I would prefer to get something like "sequential destructing not supported on maps".

I actually like the "nth not supported" error message, because it is exactly the problem, nth, used by sequential destructuring, doesn't work on maps.

it conveys exactly what the problem is if you know how destructing works and what nth means, where as "UnsupportedOperationException let cannot destructure class clojure.lang.PersistentArrayMap" seems misleading when you are in the know

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-5 (reported by alex+import)
...