A Bug of map function?

120 views
Skip to first unread message

Eric Fong

unread,
Feb 13, 2012, 4:02:34 AM2/13/12
to Clojure
=> (eval `'~(map identity [1 2 3]))
(1 2 3)

=> (eval `'~(map identity ()))
CompilerException java.lang.UnsupportedOperationException: Unknown
Collection type, compiling:(NO_SOURCE_PATH:135)

=> (eval `'~(map identity nil))
CompilerException java.lang.UnsupportedOperationException: Unknown
Collection type, compiling:(NO_SOURCE_PATH:138)

try the above in repl, clojure 1.3, why the exception occured?

Alan Malloy

unread,
Feb 13, 2012, 2:06:30 PM2/13/12
to Clojure
If this is a bug, it's in eval, not in map. eval apparently just
doesn't like to be handed lazy sequences, or something:

repl-1=> (eval `(quote ~(lazy-seq nil)))
CompilerException java.lang.UnsupportedOperationException: Unknown
Collection type, compiling:(NO_SOURCE_PATH:14)

;; just to demonstrate that these are the same value:
repl-1=> (= `(quote ~(lazy-seq nil))
repl-1=* `'~(map identity ()))
true

This looks like it's caused by
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L2680
- it should probably be testing for ISeq, not IPersistentList.

Eric Fong

unread,
Feb 13, 2012, 10:25:27 PM2/13/12
to Clojure
Thanks Alan.
Hope this will be changed.

On 2月14日, 上午3时06分, Alan Malloy <a...@malloys.org> wrote:
> If this is a bug, it's in eval, not in map. eval apparently just
> doesn't like to be handed lazy sequences, or something:
>
> repl-1=> (eval `(quote ~(lazy-seq nil)))
> CompilerException java.lang.UnsupportedOperationException: Unknown
> Collection type, compiling:(NO_SOURCE_PATH:14)
>
> ;; just to demonstrate that these are the same value:
> repl-1=> (= `(quote ~(lazy-seq nil))
> repl-1=* `'~(map identity ()))
> true
>
> This looks like it's caused byhttps://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/C...

Stuart Sierra

unread,
Feb 14, 2012, 5:00:09 PM2/14/12
to clo...@googlegroups.com
A sequence is equal to a list because Clojure defines = to compare similar collections by their contents. For example, the vector [1 2 3] is equal (by the = function) to the list (1 2 3).

`eval` calls the Clojure compiler. The compiler operates on lists returned by the reader, so I would not expect it to work on lazy sequences.

-S

Cedric Greevey

unread,
Feb 14, 2012, 8:33:44 PM2/14/12
to clo...@googlegroups.com

Macro expansions can use lazy sequences and work; e.g.

(defmacro ...
...
~(map ...)
...)

I think what's legal in a macro output should be legal in eval input.
More to the point, if it looks and quacks like a (list of thingies) it
should behave as one if evaluated, precisely because transforming
forms using the native sequence functions is a powerful
metaprogramming technique and having to wrap every such thing in
(apply list ...) or (list* ...) is going to be a pain that might as
well be avoidable and easily is avoidable.

Armando Blancas

unread,
Feb 14, 2012, 8:44:39 PM2/14/12
to Clojure
eval doesn't mind lazy seqs as input:

user=> (map identity ['quote ()])
(quote ())
user=> (class (map identity ['quote ()]))
clojure.lang.LazySeq
user=> (eval (map identity ['quote ()]))
()

But it can't handle a form that contains an (evaluated) empty lazy
seq. Another example:
user=> (eval `(quote ~(range -1)))
CompilerException java.lang.UnsupportedOperationException: Unknown
Collection type, compiling:(NO_SOURCE_PATH:53)

I think Alan pointed to bug. The empty-expr needs to check for LazySeq
instances as well.

Eric Fong

unread,
Feb 16, 2012, 4:52:01 AM2/16/12
to Clojure
That's the point. Empty lazy sequence doesn't work, but not empty lazy
sequence works.

Yixun Fang

unread,
Feb 16, 2012, 4:53:20 AM2/16/12
to Clojure
Reply all
Reply to author
Forward
0 new messages