# Scheme Programming/List Operations

Lists are a fundamental data structure in Scheme, as they are in many other functional languages. While among the simplest of structures, they have a rich set of operations and an amazing variety of uses. In this section, we'll cover the basics of creating and using lists.

## Scheme Lists

editA list is a sequence of elements ending with `()`

, sometimes called
the "empty list" or "nil". We can build up lists with `cons`

, which
attaches a new element to the head of a list:

```
> '() ; The empty list must be quoted.
()
> (cons 3 '())
(3)
> (cons 2 (cons 3 '()))
(2 3)
> (cons #t (cons 2 (cons 3 '())))
(#t 2 3)
```

The first argument of `cons`

may be any Scheme object, and
the second is a list; the value of `(cons x xs)`

is a new list which
contains `x`

followed by the elements of `xs`

.^{[1]} (Scheme's way of
printing lists uses a shorthand which hides the final `()`

. In
the responses above, we simply see the elements of a list enclosed in
parentheses.) It's important to note that we must always quote `()`

,
in order to prevent Scheme from trying to interpret it as an (invalid)
expression.

Two predicates define the Scheme list type. `null?`

,
is true for `()`

(the empty list) and is false otherwise, while
`pair?`

returns true only for objects constructed with
`cons`

.^{[2]}

There are two basic functions for accessing the elements of lists. The first,
`car`

,
extracts the first element of a list:

```
> (car (cons 1 '()))
1
> (car (cons 2 (cons 3 '())))
2
> (car '())
; Error!
```

Applying `car`

to the empty list causes an error.

The second function, `cdr`

, gives us the tail of a list: that is, the
list without its leading element:

```
> (cdr (cons 1 '()))
()
> (cdr (cons 2 (cons 3 '())))
(3)
> (cdr '())
; Error!
```

As with `car`

, trying to apply `cdr`

to the empty list causes an error.

The three functions `cons`

, `car`

, and `cdr`

satisfy some useful
identities. For any Scheme object *x* and list *xs*, we have

```
(car (cons x xs)) = x
(cdr (cons x xs)) = xs
```

For any non-empty list *ys*, we also have

```
(cons (car ys) (cdr ys)) = ys
```

Clearly, building a list through successive `cons`

operations
is clumsy. Scheme provides the built-in function `list`

which
returns a list of its arguments:

```
> (list 1 2 3 4)
(1 2 3 4)
> (cons 1 (cons 2 (cons 3 (cons 4 '())))) ; equivalent, but tedious
(1 2 3 4)
```

`list`

can take any number of arguments.

We can write a range of useful functions using just `cons`

, `car`

,
and `cdr`

. For example, we can define a function to compute the length of
a list:

```
(define (length xs)
(if (null? xs)
0
(+ 1 (length (cdr xs)))))
```

This definition, like the definitions of most list operations, closely follows
the recursive structure of a list. There is a case for the empty
list (which is assigned the length 0), and a case for a non-empty list (the length
of the tail of the list, plus one). In practice, Scheme provides
`length`

as a built-in function.

Here's another simple example:

```
(define (find-number n xs)
(if (null? xs)
#f
(if (= n (car xs))
#t
(find-number n (cdr xs)))))
```

`find-number`

returns `#t`

if the argument *n* occurs in the list
*xs*, and returns `#f`

otherwise. Once again, this definition follows
the structure of the list argument. The empty list has no elements,
so `(find-number n '())`

is always false. If `xs`

is non-empty, then
*n* could be the first element, or it could be somewhere in the tail.
In the former case, `find-number`

returns true immediately. In the
latter, the return value should be true if *n* appears in `(cdr xs)`

and false otherwise. But since this is the definition of `find-number`

itself, we have a recursive call with the new argument `(cdr xs)`

.

## Notes

edit- ↑ This
is a simplified account which is correct for our current purposes. In fact,
`cons`

constructs*pairs*of its arguments, both of which may be arbitrary Scheme objects. A pair whose second element is`()`

or another pair is called a list; all other pairs are called*improper*. - ↑ The definition of the Scheme list type is
looser than that of numbers, booleans, etc.
While the (scheme list) library provides a true
`list?`

function, this function is defined in terms of`null?`

and`pair?`

. See the previous note.