5

I've been given an assignment in Scheme (using DrRacket) that asks me to create the list ((1 2) 3) using cons, from the components 1, 2, 3 and ()

I've managed to get as far as ((1 2) . 3) using:

(cons (cons '1 (cons '2 '())) '3)

However, is that the same thing?

karoma
  • 1,548
  • 5
  • 24
  • 43
  • [This answer](http://stackoverflow.com/a/16379759/1281433) (disclaimer, it's my answer) to question where someone was getting output like `((1 2) . 3)` instead of `((1 2) 3)` explains the printed notation of lists and cons cells. The short answer is that `((1 2) 3)` and `((1 2) . 3)` are _not_ the same. The first is `(cons (cons 1 (cons 2 ())) (cons 3 ()))` and the second is `(cons (cons 1 (cons 2 ())) 3)`. – Joshua Taylor Oct 07 '13 at 14:54

5 Answers5

5

Note: this is cannibalized from my answer to Recursive range in Lisp adds a period? The question is different (so not a duplicate), but the background explanation of how lists are constructed from cons cells, and how they're printed is the same. The end is a bit different.

A list in Scheme is either the empty list () (also known as nil in some Lisps), or a cons cell whose car (also known as first) is an element of the list and whose cdr (also known as rest) is either the rest of the list (i.e., another list), or an atom that terminates the list. The conventional terminator is the empty list (); lists terminated by () are said to be "proper lists". Lists terminated by any other atom are called "improper lists". The list (1 2 3 4 5) contains the elements 1, 2, 3, 4, and 5, and is terminated by (). You could construct it by

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))

Now, when the system prints a cons cell, the general case is to print it by

(car . cdr)

For instance, the result of (cons 1 2) is printed as

(1 . 2)

Since lists are built of cons cells, you can use this notation for lists too:

'(1 2 3 4 5)                      ; ==
'(1 . (2 . (3 . (4 . (5 . ())))))

That's rather clunky, though, so most lisps (all that I know of) have a special case for printing cons cells: if the cdr is a list (either another cons cell, or ()), then don't print the ., and don't print the surrounding parenthesis of the cdr (which it would otherwise have, since it's a list).

With this understanding of lists and cons cells, we can consider the specific cases ((1 2) 3) and ((1 2) . 3). Let's break each of these down into the cons cells.

((1 2) 3)                              ; ==
((1 . (2 . ()) . (3 . ()))             ; ==
(cons (cons 1 (cons 2 ()) (cons 3 ()))  
((1 2) . 3)                   ; ==           
((1 . (2 . ())) . 3)          ; ==
(cons (cons 1 (cons 2 ())) 3)

The last lines in each case are different, so ((1 2) 3) and ((1 2) . 3) are not the same.

Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
2

No, as others have mentioned, ((1 2) 3) is the same as ((1 2) 3 . ()), which of course you can build using (cons '3 '()) instead of the literal '3:

(cons (cons '1 (cons '2 '())) (cons '3 '()))
Justin Ethier
  • 131,333
  • 52
  • 229
  • 284
1

No.

The "top-level" element of (A . B) is a single cons cell: (cons A B). The car of the cons cell is A and the cdr is B. In a proper list, the cdr elements are always either () or other nonempty proper lists.

In contrast, (A B) is a two-element list, with one cons cell for each element: (cons A (cons B ()))

svk
  • 5,854
  • 17
  • 22
1

They are different. ((1 2) 3) is a '() terminated list while ((1 2) . 3) is just a "pair". Try replacing '3 with (cons '3 '())

hugomg
  • 68,213
  • 24
  • 160
  • 246
1

They're different:

(equal? '((1 2) 3) '((1 2) . 3))
=> #f

Because '((1 2) 3) is equivalent to this:

(cons (cons 1 (cons 2 '())) (cons 3 '()))

Whereas '((1 2) . 3) is equivalent to this:

(cons (cons 1 (cons 2 '())) 3)

So you see, they have a different cons cell structure. The first version is a proper list - meaning: it ends in the empty list '(), whereas the second version ends in 3, making it an improper list.

Óscar López
  • 232,561
  • 37
  • 312
  • 386