views:

235

answers:

5

(Disclaimer - I'm aware of the significance of Seqs in Clojure)

In common lisp the cons function can be used to combine two symbols into a list:

(def s 'x)
(def l 'y)
(cons s l)

In clojure - you can only cons onto a sequence - cons hasn't been extended to work with two symbols. So you have to write:

(def s 'x)
(def l 'y)
(cons s '(l))

Is there a higher level pattern in Clojure that explains this difference between Common LISP and Clojure?

+1  A: 

When you say

> (cons 'a 'b)

in common lisp you dont get a list but a dotted pair: (a . b), whereas the result of

> (cons 'a (cons 'b nil))

is the dotted pair (a . ( b . nil)).

In the first list the cdr() of that is not a list, since it is here b and not nil, making it an improper list. Proper lists must be terminated by nil. Therefore higher order functions like mapcar() and friends won't work, but we save a cons-cell. I guess the designers of Clojure removed this feature because of the confusion it could cause.

johanbev
It should be noted that `(a . (b . nil))` _is_ a Lisp list, commonly noted as `(a b)`.
Svante
+7  A: 

In Clojure, unlike traditional Lisps, lists are not the primary data structures. The data structures can implement the ISeq interface - which is another view of the data structure it's given - allowing the same functions to access elements in each. (Lists already implement this. seq? checks whether something implements ISeq.(seq? '(1 2)), (seq? [1 2])) Clojure simply acts differently (with good reason), in that when cons is used, a sequence (it's actually of type clojure.lang.Cons) constructed of a and (seq b) is returned. (a being arg 1 and b arg 2) Obviously, symbols don't and can't implement ISeq.

Clojure.org/sequences

Sequences screencast/talk by Rich Hickey However, note that rest has changed, and it's previous behaviour is now in next, and that lazy-cons has been replaced by lazy-seq and cons.

clojure.lang.RT

MayDaniel
+4  A: 

In Common Lisp CONS creates a so-called CONS cell, which is similar to a record with two slots: the 'car' and the 'cdr'.

You can put ANYTHING into those two slots of a cons cell.

Cons cells are used to build lists. But one can create all kinds of data structures with cons cells: trees, graphs, various types of specialized lists, ...

The implementations of Lisp are highly optimized to provide very efficient cons cells.

Rainer Joswig
+3  A: 

A Lisp list is just a common way of using cons cells (see Rainer's description). Clojure is best seen as not having cons cells (although something similar might hide under the hood). The Clojure cons is a misnomer, it should actually just be named prepend.

Svante
+2  A: 

In Clojure the use of a two-element vector is preferred: [:a :b]. Under the hood such small vectors are implemented as Java arrays and are extremely simple and fast.

A short hand for (cons :a '(:b)) (or (cons :a (cons :b nil))) is list: (list :a :b).

kotarak