Search code examples
listschemeracketcons

Why do nested applications of cons construct improper lists?


What do nested applications of cons construct improper lists? I am learning scheme and confused about cons. I came across this answer:

Cons element to list vs cons list to element in Scheme

I know when the second argument to cons is a list , it adds the first argument to the head of the list

(cons 1 (list 2 3) 
=>'(1 2 3)

The following pair makes sense to me:

(cons 2 3); 2.3 pair

However I don't understand why the following expression constructs an improper list

(cons 1 (cons 2 3))
=> '(1 2 . 3)   ; an improper list

I just can't visualize what's going on with the expression above

can you please elaborate on that?


Solution

  • The confusion you're experiencing is not unique. It's just notation, that is all, and until you learn to see that notation, everything is confusing.

    First, let's start with proper lists. These are lists that end with an empty list:

    (cons 1 (cons 2 (cons 3 '())))
    ; => (1 2 3)
    

    This list, (1 2 3), is actually a shorthand for (1 2 3 . ()): basically a list where the last cons points to an empty list.

    Now, if we substitute the () with 4, let's see what we get:

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

    Notice, it's not so different from (1 2 3 . ()), is it?

    Of course, both of these are shorthands for the much longer forms of (1 . (2 . (3 . ()))) and (1 . (2 . (3 . 4))), respectively.