list* not returning a list

148 views
Skip to first unread message

Marek Šrank

unread,
Dec 26, 2012, 3:35:25 PM12/26/12
to clo...@googlegroups.com
function list* doesn't return a list, because it uses 'cons' under the hood:

(list? (list* 1 2 3 '()))
;=> false

(class (list* 1 2 3 '()))
;=> clojure.lang.Cons

...however, its docstring says: "Creates a new list containing the items prepended to the rest, the last of which will be treated as a sequence."

I think that this can be pretty confusing... Shouldn't it be fixed (at least the docstring)?


Cheers,
Marek.

Stephen Compall

unread,
Dec 26, 2012, 5:07:01 PM12/26/12
to clo...@googlegroups.com
On Wed, 2012-12-26 at 12:35 -0800, Marek Šrank wrote:
> ...however, its docstring says: "Creates a new list containing the items
> prepended to the rest, the last of which will be treated as a sequence."

List is almost always colloquial, not literally IPersistentList.

I would be in favor of eliminating list?, really, in favor of
seq?/sequential?/seqable?.

> I think that this can be pretty confusing... Shouldn't it be fixed (at
> least the docstring)?

http://dev.clojure.org/jira/

--
Stephen Compall
^aCollection allSatisfy: [:each|aCondition]: less is better

Ben Wolfson

unread,
Dec 26, 2012, 5:13:38 PM12/26/12
to clo...@googlegroups.com
On Wed, Dec 26, 2012 at 2:07 PM, Stephen Compall
<stephen...@gmail.com> wrote:
> On Wed, 2012-12-26 at 12:35 -0800, Marek Šrank wrote:
>> ...however, its docstring says: "Creates a new list containing the items
>> prepended to the rest, the last of which will be treated as a sequence."
>
> List is almost always colloquial, not literally IPersistentList.
>
> I would be in favor of eliminating list?, really, in favor of
> seq?/sequential?/seqable?.

Given that lists and (e.g.) vectors behave differently in some
circumstances (as the first argument to conj, for instance), it seems
desirable to be able to tell what one's got on one's hands.

--
Ben Wolfson
"Human kind has used its intelligence to vary the flavour of drinks,
which may be sweet, aromatic, fermented or spirit-based. ... Family
and social life also offer numerous other occasions to consume drinks
for pleasure." [Larousse, "Drink" entry]

Tom Jack

unread,
Dec 26, 2012, 9:28:04 PM12/26/12
to clo...@googlegroups.com
A small bug in ClojureScript was related to this: https://github.com/clojure/clojurescript/commit/88b36c177ebd1bb49dbd874a9d13652fd1de4027

It looks like the only thing missing to make Cons implement IPersistentList is IPersistentStack. Why not implement it?

Ben Wolfson

unread,
Dec 27, 2012, 11:06:19 AM12/27/12
to clo...@googlegroups.com
On Wed, Dec 26, 2012 at 6:28 PM, Tom Jack <t...@tomoj.la> wrote:
> A small bug in ClojureScript was related to this:
> https://github.com/clojure/clojurescript/commit/88b36c177ebd1bb49dbd874a9d13652fd1de4027
>
> It looks like the only thing missing to make Cons implement IPersistentList
> is IPersistentStack. Why not implement it?

This seems very weird to me:

> (list? (cons 1 '()))
false

Especially since:

> (list? (empty (cons 1 '())))
true

making list? true of cons cells would presumably also eliminate the
need for those awkward (apply list ...)s in, e.g., clojure.walk/walk.

Michał Marczyk

unread,
Dec 27, 2012, 12:08:30 PM12/27/12
to clo...@googlegroups.com
On 27 December 2012 03:28, Tom Jack <t...@tomoj.la> wrote:
> It looks like the only thing missing to make Cons implement IPersistentList
> is IPersistentStack. Why not implement it?

IPersistentStack extends IPersistentCollection, which includes
count(), so that's no go for Cons (the rest part might be a lazy seq).

Cheers,
M.


>
>
> On Wednesday, December 26, 2012 4:13:38 PM UTC-6, Ben wrote:
>>
>> On Wed, Dec 26, 2012 at 2:07 PM, Stephen Compall
>> <stephen...@gmail.com> wrote:
>> > On Wed, 2012-12-26 at 12:35 -0800, Marek Šrank wrote:
>> >> ...however, its docstring says: "Creates a new list containing the
>> >> items
>> >> prepended to the rest, the last of which will be treated as a
>> >> sequence."
>> >
>> > List is almost always colloquial, not literally IPersistentList.
>> >
>> > I would be in favor of eliminating list?, really, in favor of
>> > seq?/sequential?/seqable?.
>>
>> Given that lists and (e.g.) vectors behave differently in some
>> circumstances (as the first argument to conj, for instance), it seems
>> desirable to be able to tell what one's got on one's hands.
>>
>> --
>> Ben Wolfson
>> "Human kind has used its intelligence to vary the flavour of drinks,
>> which may be sweet, aromatic, fermented or spirit-based. ... Family
>> and social life also offer numerous other occasions to consume drinks
>> for pleasure." [Larousse, "Drink" entry]
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

Ben Wolfson

unread,
Dec 27, 2012, 12:52:58 PM12/27/12
to clo...@googlegroups.com
On Thu, Dec 27, 2012 at 9:08 AM, Michał Marczyk
<michal....@gmail.com> wrote:
> On 27 December 2012 03:28, Tom Jack <t...@tomoj.la> wrote:
>> It looks like the only thing missing to make Cons implement IPersistentList
>> is IPersistentStack. Why not implement it?
>
> IPersistentStack extends IPersistentCollection, which includes
> count(), so that's no go for Cons (the rest part might be a lazy seq).

Doesn't stop existing lazy seqs:


user=> (def x (repeat 2))
#'user/x
user=> (coll? x)
true
user=> (instance? clojure.lang.IPersistentCollection x)
true
user=> (count x)
; predictable lack of results

Marek Šrank

unread,
Dec 27, 2012, 2:37:20 PM12/27/12
to clo...@googlegroups.com
Making Cons implement IPersistentList will solve all cases except when list* gets only one argument. This is problematic. The source looks like this:

(defn list*
  "Creates a new list containing the items prepended to the rest, the
  last of which will be treated as a sequence."
  {:added "1.0"
   :static true}
  ([args] (seq args))
  ([a args] (cons a args))
  ([a b args] (cons a (cons b args)))
  ([a b c args] (cons a (cons b (cons c args))))
  ([a b c d & more]
     (cons a (cons b (cons c (cons d (spread more)))))))

Calling 'seq' in the first case means that with calls like: (list* {:a 1}) we get clojure.lang.PersistentArrayMap$Seq and not a List. In theory, we could do just (apply list args) here, but apply itself also uses list* in its implementation. Luckily, it doesn't use the one-argument version of list*, so we could probably declare 'apply' above the 'list*' in the 'core.clj' source and then use it there... Does it seem reasonably?

Marek

Michał Marczyk

unread,
Dec 27, 2012, 4:00:07 PM12/27/12
to clo...@googlegroups.com
On 27 December 2012 18:52, Ben Wolfson <wol...@gmail.com> wrote:
> On Thu, Dec 27, 2012 at 9:08 AM, Michał Marczyk
> <michal....@gmail.com> wrote:
>> On 27 December 2012 03:28, Tom Jack <t...@tomoj.la> wrote:
>>> It looks like the only thing missing to make Cons implement IPersistentList
>>> is IPersistentStack. Why not implement it?
>>
>> IPersistentStack extends IPersistentCollection, which includes
>> count(), so that's no go for Cons (the rest part might be a lazy seq).
>
> Doesn't stop existing lazy seqs:

Oh, indeed. Thanks!


>
>
> user=> (def x (repeat 2))
> #'user/x
> user=> (coll? x)
> true
> user=> (instance? clojure.lang.IPersistentCollection x)
> true
> user=> (count x)
> ; predictable lack of results
>
> --
> Ben Wolfson
> "Human kind has used its intelligence to vary the flavour of drinks,
> which may be sweet, aromatic, fermented or spirit-based. ... Family
> and social life also offer numerous other occasions to consume drinks
> for pleasure." [Larousse, "Drink" entry]
>

Marek Šrank

unread,
Jan 4, 2013, 3:06:26 PM1/4/13
to clo...@googlegroups.com
I found CLJ-1060 [1] and added there a patch with Cons implementing IPersistentList and (apply list args) in one-argument case of list*. 

Michał Marczyk

unread,
Jan 4, 2013, 5:16:41 PM1/4/13
to clo...@googlegroups.com
Hey,

I replied in the ticket with some comments. The main issue I see is
that I'm used to the notion that IPersistentLists are things which are
not lazy and which have next/rest parts which are themselves IPLs and
this approach seems to cause that no longer to be the case. If it were
not to be the case, then the question arises why maintain the list/seq
distinction at all. Will be interesting to read further opinions on
this!

Cheers,
Michał
Reply all
Reply to author
Forward
0 new messages