Go to the first, previous, next, last section, table of contents.


Building Lists

It has already been shown how you can create lists using the Lisp reader; this method does have a drawback though: the list created is effectively static. If you modify the contents of the list and that list was created when a function was defined the list will remain modified for all future invocations of that function. This is not usually a good idea, consider the following function definition,

(defun bogus-function (x)
  "Return a list whose first element is nil and whose second element is X."
  (let
      ((result '(nil nil)))     ;Static list which is filled in each time
    (rplaca (cdr result) x)     ; the function is called
    result))

This function does in fact do what its documentation claims, but a problem arises when it is called more than once,

(setq x (bogus-function 'foo))
    => (nil foo)
(setq y (bogus-function 'bar))
    => (nil bar)               ;The first result has been destroyed
x
    => (nil bar)               ;See!

This example is totally contrived -- no one would ever write a function like the one in the example but it nicely demonstrates the need for a dynamic method of creating lists.

Function: list &rest elements
This function creates a list out of its arguments, if zero arguments are given the empty list, nil, is returned.

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

(list (major-version-number) (minor-version-number))
    => (3 2)

(list)
    => nil               ;Equivalent to `()'

Function: make-list length &optional initial-value
This function creates a list length elements long. If the initial-value argument is given it defines the value of all elements in the list, if it is not given they are all nil.

(make-list 2)
    => (nil nil)

(make-list 3 t)
    => (t t t)

(make-list 0)
    => nil

Function: append &rest lists
This function creates a new list with the elements of each of its arguments (which must be lists). Unlike the function nconc this function preserves all of its arguments.

(append '(1 2 3) '(4 5))
    => (1 2 3 4 5)

(append)
    => nil

What actually happens is that all arguments but the last are copied then the last argument is linked on to the end of the list (uncopied).

(setq foo '(1 2))
    => (1 2)
(setq bar '(3 4))
    => (3 4)
(setq baz (append foo bar))
    => (1 2 3 4)
(eq (nthcdr 2 baz) bar)
    => t

The following diagram shows the final state of the three variables more clearly,

foo--> +-----+-----+   +-----+-----+
       |  o  |  o----> |  o  |     |
       +--|--+-----+   +--|--+-----+
          |               |
          o--> 1          o--> 2   bar
          |               |          ->
baz--> +--|--+-----+   +--|--+-----+   +-----+-----+   +-----+-----+
       |  o  |  o----> |  o  |  o----> |  o  |  o----> |  o  |     |
       +-----+-----+   +-----+-----+   +--|--+-----+   +--|--+-----+
                                          |               |
                                           --> 3           --> 4

Note how foo and the first half of baz use the same objects for their elements -- copying a list only copies its cons cells, its elements are reused. Also note how the variable bar actually references the mid-point of baz since the last list in an append call is not copied.

Function: reverse list
This function returns a new list; it is made from the elements of the list list in reverse order. Note that this function does not alter its argument.

(reverse '(1 2 3 4))
    => (4 3 2 1)

As a postscript to this section, the function used as an example at the beginning could now be written as,

(defun not-so-bogus-function (x)
  (list nil x))

Also note that the cons function can be used to create lists by hand and to add new elements onto the front of a list.


Go to the first, previous, next, last section, table of contents.