user=> (doc cons)
-------------------------
clojure.core/cons
([x seq])
Returns a new seq where x is the first element and seq is
the rest.
nil
user=> (cons 4 '(1 2 3))
(4 1 2 3)
user=> (seq? (cons 4 '(1 2 3)))
true
user=> (first (cons 4 '(1 2 3)))
4
user=> (rest (cons 4 '(1 2 3)))
(1 2 3)
user=> (list? (rest (cons 4 '(1 2 3))))
true
user=>
cons is acting according to its documentation.
Some of the roles played by lists in other Lisps are played by seqs in
Clojure. Also, in Clojure a list is not a linked list of cons cells.
Roughly speaking, a Clojure list is a linked list of lists:
user=> (list? (rest (rest (rest '(1 2 3 4 5 6 7)))))
true
--Steve
That's not strictly true:
user=> (doc list?)
-------------------------
clojure.core/list?
([x])
Returns true if x implements IPersistentList
nil
user=> (cons 5 '(1 2 3))
(5 1 2 3)
user=> (ancestors (type *1))
#{clojure.lang.IMeta java.lang.Iterable java.util.Collection
clojure.lang.ISeq java.util.List clojure.lang.Seqable clojure.lang.Obj
clojure.lang.IObj java.lang.Object clojure.lang.Sequential
clojure.lang.IPersistentCollection clojure.lang.Streamable
clojure.lang.ASeq}
... the result of cons does not implement IPersistentList, so list? is
acting according to its documentation.
Is there a reason why you are testing for listiness rather than for
some other property, like Sequential? It's generally considered good
form in Clojure to program against the native abstractions (such as
sequences) rather than particular concrete types.
-R
Am 28.06.2009 um 07:45 schrieb Handkea fumosa:
> It's list? that isn't.
No. list? is not broken. Every list is a seq, but not
every seq is a list.
Consider: (cons 0 (iterate inc 1))
This is no list! It's a sequence. Why should list?
return true?
In Clojure there is no such thing as a cons cell.
There is only an abstraction of a cons cell where
the second part must implement again the
sequence abstraction.
If you need a cons cell, use a two-element vector
or a two-element list.
Please: If you want to program CL in Clojure...
Don't do it. Clojure is different. Claiming parts
of Clojure are broken because they don't behave
like something is else doesn't make sense and
hence leads nowhere.
If you want to try Clojure, make up your mind
and learn Clojure's environment. Thinking
Python/Perl/CL/whatever in Clojure will only
hinder your progress with Clojure.
If you find a bug, where a function violates its
documented contract, please report it.
Sincerely
Meikel
PS: This is no Clojure specific issue. Trying to
learn Python and program it like one would in
Clojure, also doesn't work...
This is overstating things. There certainly is a cons cell, it's
called Cons, and cons produces one. It differs from CL cons cell in
not being an arbitrary pair (i.e. the rest must be a sequence or nil).
> Please: If you want to program CL in Clojure...
> Don't do it. Clojure is different. Claiming parts
> of Clojure are broken because they don't behave
> like something is else doesn't make sense and
> hence leads nowhere.
>
This too is a bit much. The OP wasn't trying to use cons as a pair,
just expecting list? to be more similar to listp. It's a reasonable
mistake, please be gentle.
Because Clojure supports a seq abstraction, there is heterogeneity in
the implementations. In fact there are two cons-cell-like data
structures:
user=> (class (cons 4 '(1 2 3)))
clojure.lang.Cons
user=> (counted? (cons 4 '(1 2 3)))
false
user=> (class (conj '(1 2 3) 4))
clojure.lang.PersistentList
user=> (counted? (conj '(1 2 3) 4))
true
So, list? is more specific because seqs are more general. seq? is
probably what is desired.
cons onto an IPersistentList could be made to return another
IPersistentList, but currently doesn't.
Rich
Not a liar; just misinformed, as I hope I demonstrated by citing the
docs. I don't see any value in continuing this thread of the
discussion, but I wanted to clear that up.
> If you don't think list? should be true for all () collections, or at
> least all finite ones, perhaps the core should contain a function that
> is? We have set?, vector?, and map? for [], #{}, and {} collections
> respectively that exactly distinguish them from others. But for ()
> collections we only seem to have #(and (sequential? %) (not (vector?
> %))).
As Rich pointed out, seq? is what you want.
user=> (seq? [])
false
user=> (cons 5 [])
(5)
user=> (seq? *1)
true