4

I have the following code:

(progn 3 4)                ;; => 4 
(list 1 (progn 3 4))       ;; => (1 4) 
(car (list 1 (progn 3 4))) ;; => 1 

I understand these return values. But why does the following:

(cdr (list 1 (progn 3 4))  ;; => (4)

Return (4) rather than 4? I would have thought 4, so what am I misunderstanding here?

  • 6
    Note that this is not Emacs-specific, the same rule applies to all Lisps. I'd recommend reading some intro to lisp programming. – nanny Jun 22 '15 at 14:46
11

Here's the docstring for cdr:

(cdr LIST)

Return the cdr of LIST. If arg is nil, return nil. Error if arg is not nil and not a cons cell. See also `cdr-safe'.

See Info node `(elisp)Cons Cells' for a discussion of related basic Lisp concepts such as cdr, car, cons cell and list.

cdr returns the second slot of the cons cell, which is referring to the rest of the list -- in your case, the rest of the list is one element long, but it's still a list.

Look at the manual for more information on cons cells. In particular:

Function: cdr cons-cell

This function returns the value referred to by the second slot of the cons cell cons-cell. In other words, it returns the CDR of cons-cell.

As a special case, if cons-cell is nil, this function returns nil; therefore, any list is a valid argument. An error is signaled if the argument is not a cons cell or nil.

(cdr '(a b c))
     ⇒ (b c)
6

When given a list cdr returns a list from second element to the end:

(car '(1 2 3)) ; ⇒ 1
(cdr '(1 2 3)) ; ⇒ (2 3)

Exceptions to this include:

  • lists of fewer than two elements:

    (cdr nil)  ; ⇒ nil
    (cdr '(1)) ; ⇒ nil
    
  • things like '(1 . 2) (which are produced with e.g. (cons 1 2)):

    (cdr '(1 . 2)) ; ⇒ 2
    
  • I don't think it's good to generalize because it'll only confuse people when it returns nil or an atom. – nanny Jun 22 '15 at 14:47
  • What is with (cdr (cons 1 2))?? Please, delete this non-answer. – Tobias Jun 22 '15 at 15:42
  • @Tobias: seems to be fixed. – Adobe Jun 22 '15 at 16:44
  • @nanny: now I added this case. – Adobe Jun 22 '15 at 16:47
  • (listp (cons 1 2)) rightfully returns t and (listp nil), too. – Tobias Jun 22 '15 at 16:48
4

Old question, but I may as well explain why cdr acts the way it does in case someone Googles the question later...

cdr acts this way because lists in Lisps like Elisp are not quite lists like how you would imagine them, they are actually made up of things called cons cells.

Essentially, when you make a list, it isn't a simple collection of items, one after another--it's actually just a chain of tiny lists, each only capable of holding two values. These pairs are the "cons cells".

In each pair, the first value holds the value of the list at that point, and the second holds either "nil" (End of the list), or a reference to another cons cell (The next item in the list).

So:

ELISP> (list 1)
(1)

Is the same as:

ELISP> (cons 1 nil)
(1)

And:

ELISP> (list 1 4)
(1 4)

Is the same as:

ELISP> (cons 1 (cons 4 nil))
(1 4)

...and so forth.

Now, what car and cdr do is take the first and second values of these cons cells.

So, looking at your list when expanded to cons cells (That's (cons 1 (cons 4 nil))):

ELISP> (car (cons 1 (cons 4 nil)))
1

Because the first value of the outer cons is "1", and:

ELISP> (cdr (cons 1 (cons 4 nil)))
(4)

Because the second value of the outer cons is "(cons 4 nil)" and:

ELISP> (cons 4 nil)
(4)

It is possible for a cdr to hold something other than nil or a reference to another cons cell, but these are not the same type of list, but rather a "dotted pair":

ELISP> (cons 1 4)
(1 . 4)
ELISP> (car (cons 1 4))
1
ELISP> (cdr (cons 1 4))
4

Hopefully this clears some things up..!

  • "tiny lists" confuses more than it helps. Would be an improvement to just replace with "chain of cons cells". Because that's what any list in any Lisp is. – Jürgen A. Erhard Jan 1 '17 at 20:40
  • What's the result of (cdddr '(1 2 3 . 4))? (And yes, valid Elisp, just tested :D) – Jürgen A. Erhard Jan 1 '17 at 20:42
  • Well, I said cons cells were basically "tiny lists that can only hold two values" because I was assuming the reader didn't know what a cons cell was. With that in mind, if you can think of a better way of explaining them, feel free to submit an edit to the answer. – Archenoth Jan 3 '17 at 6:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.