Next: , Up: lists   [Index]


23.1 Introduction

Scheme does not properly have a list type, just as the C language does not have a string type. Rather, Scheme has a binary–tuple type, from which one can build binary trees. There is an interpretation of Scheme values that allows one to treat these trees as lists. Further complications ensue from the fact that Scheme allows side–effects to these tuples, raising the possibility of lists of unbounded length, and trees of unbounded depth (that is, circular data structures).

What follows is a classification of concrete values with respect to list as an abstract concept.

Null value

It is a special value which can be identified with the predicate null?. Null is meant to represent empty lists and to be the terminator for proper lists.

length applied to null returns zero. In light of what follows, it makes sense to consider null as a list of length zero for all the list classes: proper, circular, dotted, generalised.

Proper lists

A finite, null–terminated list; more precisely a proper list is defined as: A pair whose cdr is a proper list or null. The opposite of proper is improper; everything that is not null or a proper list, is an improper list.

(a b c)
(32)

We can build a proper list in a single function call with list, or we can do it in steps using cons and cons*; we can detect if a list is proper with list?.

Circular list

An infinite, unterminated list; a circular list is a value such that cdr applied any number of times always returns a pair. The opposite of circular is finite.

We can build a list having a circular tail as follows:

(define end  (cons  1 '()))
(define tail (cons* 3 2 end))
(define ell  (cons* 5 4 tail))
(set-cdr! end tail)

the list structure bound to ‘ell’ looks like this:

                           cdr
                  ----------------
                 |                |
     cdr    cdr  v cdr    cdr     |
   O----->O----->O----->O----->O--
   |      |      |      |      |
car|   car|   car|   car|   car|
   v      v      v      v      v
   5      4      3      2      1

so that the following happens:

(car ell)            ⇒ 5
(cadr ell)           ⇒ 4
(caddr ell)          ⇒ 3
(cadddr ell)         ⇒ 2
(cadddr (cdr ell))   ⇒ 1
(cdddr (cddr ell))   ⇒ tail
(cadddr (cddr ell))  ⇒ 3
(cadddr (cdddr ell)) ⇒ 2

it is impossible to build a circular list without mutating a pair. Notice that the following is not a circular list:

                           car
           --------------------
          |                    |
     cdr  v cdr    cdr    cdr  | cdr
   O----->O----->O----->O----->O----->()
   |      |      |      |
car|   car|   car|   car|
   v      v      v      v
   5      4      3      2

it is a proper list in which the car of the last pair references one of the previous pairs.

We can build a circular list, a ring, with circular-list and we can detect if a list is a ring or has a circular tail with circular-list?.

Dotted list

A finite, non–nil terminated list, such as:

(a b c . d)
(x . y)

a dotted list is a value for which there exists an integer n > 0, such that cdr applied n times yields neither a pair nor null. This means that, for a dotted list, either null? or pair? return #t.

Users of the (vicare containers lists ---) libraries should note that dotted lists are not commonly used, and are considered by many Scheme programmers to be an ugly artifact of Scheme’s lack of a true list type. However, dotted lists do play a noticeable role in the syntax of Scheme, in the “rest” parameters used by n–ary lambdas:

(lambda (x y . rest)
  ---)

Dotted lists are not fully supported by the list libraries; most procedures are defined only on proper lists. The procedures that will also handle circular or dotted lists are specifically marked. While this design decision restricts the domain of possible arguments one can pass to these procedures, it has the benefit of allowing the procedures to catch the error cases where programmers inadvertently pass scalar values to a list procedure by accident (for example, by switching the arguments to a procedure call).

Improper list

A finite, non–nil terminated list, such as:

(a b c . d)
(x . y)
42
george

a improper list is a value for which there exists an integer n >= 0, such that cdr applied n times yields neither a pair nor null. This includes non–pair, non–null values (symbols, numbers, etc.), which are considered to be improper lists of length 0. Dotted lists are improper lists.


Next: , Up: lists   [Index]