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

+1 vote
in Compiler by
closed by

I have encountered a bug when lazy-seq is passed into a quote. Here is an example which causes the issue:

user=> (eval `(quote ~(lazy-seq '(1 2 3))))
(1 2 3)

user=> (eval `(quote ~(lazy-seq '())))
Syntax error (UnsupportedOperationException) compiling fn* at (REPL:1:1).
Unknown Collection type

user=> (eval (quote ())) () ``

1 Answer

0 votes

Is there some scenario where this is relevant?

Lots of Clojure's methods will return a lazy-seq, so if quote is used on an empty collection, it can cause this issue.  For example: "`(quote ~(map a b))"

I wrote the above example using lazy-seq directly to make a minimal test case
I’m not aware of anyone running into this ever, so I’m really more interested in when someone (like yourself) might actually have run into it.
Is there any scenario not involving eval where this causes a problem? Because eval is vanishingly rare in production Clojure code.
"(defmacro m [] `'~(keep (constantly nil) (range 10)))" has the same issue.

I found that the `Compiler$EmptyExpr` doesn't deal with empty sequences properly other than empty lists. Maybe the Compiler code around here https://github.com/clojure/clojure/blob/6975553804b0f8da9e196e6fb97838ea4e153564/src/jvm/clojure/lang/Compiler.java#L2990-L2991 should handle those cases.
edited by
I had a macro that records some data using quote into a data structure.  This is something like "(defmacro m [x y]  `(swap! global-data assoc ~(foo x)  (quote ~(map bar y))))"
The issue was triggered when "y" was passed an empty vector.

I managed to work around this for now by just casting the mapped lazy seq to a vector:
"(defmacro m [x y]  `(swap! global-data assoc ~(foo x)  (quote ~(vec (map bar y)))))"
thank you, that's helpful