Association lists

Course links

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:

(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.