Consider the organization of a simple telephone directory for on-campus
telephones: a sequence of entries, each consisting of a name and a
four-digit telephone number. In Scheme, it's natural to use strings for
names; it turns out that telephone numbers should also be represented as
strings, since string operations make a useful kind of sense when applied
to telephone numbers and integer operations do not. (For instance,
(string-append "269-" extension) does something useful if the
value of extension is a string, but not if it is an integer.)
To represent each individual entry in a telephone directory, we can use a
pair, such as ("Henry Walker" . "4208") or ("John Stone"
. "3181"), with the name as the car of the entry and the telephone number
as the cdr. An entire directory, then, would be a list of such entries:
(define science-professors-directory
'(("Chuck Sullivan" . "3042")
("Leslie Lyons" . "3159")
("Royce Wolf" . "4209")
("Charles Cunningham" . "3182")
("Janet Gibson" . "3168")))
In Scheme, a list of pairs is called an association list or alist.
As the telephone-directory example illustrates, a particularly common
application of association lists involves looking for a desired name or
first component of a pair and retrieving the second component of a pair.
Thus, the first component of each pair (the car of a pair) often is called
a key, and the cdr of the pair is its associated data
or value. For example, in the above illustration, "Chuck
Sullivan", "Royce Wolf", and "Janet Gibson" are some of the
keys, and the telephone numbers are the associated data. Thus an
association list is a simple way to implement a small database.
Since such applications are very common, Scheme provides procedures to
retrieve from an association list the pair containing a specified key. The
most frequently used procedure of this kind is assoc. Given a key
and association list, assoc returns the first pair with the given
key. If the key does not occur in the association list, then assoc
returns #f. For example, the value of (assoc "Charles
Cunningham" science-professors-directory) is ("Charles Cunningham"
. "3182"), while the value of (assoc "Laurel Smith"
science-professors-directory) is #f.
To find the telephone number corresponding to a given name, we could apply
the cdr procedure to the result of assoc:
;;; look-up-telephone-number: return the telephone number ;;; associated with a given name in SCIENCE-PROFESSORS-DIRECTORY ;;; (or the symbol UNLISTED if there is none) ;;; Given: ;;; NAME, a string. ;;; Result: ;;; NUMBER, a string or a symbol. ;;; Preconditions: ;;; None. ;;; Postconditions: ;;; If NAME is a key in SCIENCE-PROFESSORS-DIRECTORY, then NUMBER ;;; is the associated value; otherwise, NUMBER is the symbol ;;; UNDEFINED. (define look-up-telephone-number (lambda (name) (if (assoc name science-professors-directory) (cdr (assoc name science-professors-directory)) 'unlisted)))
> (look-up-telephone-number "Charles Cunningham") "3182" > (look-up-telephone-number "Laurel Smith") unlisted
The assoc procedure is actually one of three related built-in
procedures in Scheme; the other two are assq and assv. Each
of these procedures scan association lists for keys. They differ only in
the test used for determining when a key is found:
assoc uses the predicate equal? to compare the key
sought with the key components of the entries in the association list.assq uses the predicate eq? for those comparisons.assv uses the predicate eqv? for those comparisons.(See the earlier reading ``Procedure definitions'' to refresh your memory of these predicates.)
The principal author of this reading is Professor Henry Walker. I am also indebted to Professor Ben Gum for his contributions to its development.