Laboratory Exercises For Computer Science 151

Pairs

Pairs

Goals: This laboratory introduces the box-and-pointer representation for lists and the dot notation. The laboratory also discusses association lists as an important application of general list structures.

Box-and-Pointer Representation: As we have often seen, Scheme uses cons to build lists. We now consider a graphical way to represent the result of a cons procedure. The basic idea is to use a rectangle - divided in half - to represent the result of the cons. From the first half of the rectangle, we draw an arrow to the head of a list; from the second half of the rectangle, we draw an arrow to the rest of the list. For example, (cons 'a '()) would be represented as follows:

Here, the line to a indicates that this is the head of the list. The diagonal line through the right half of the rectangle indicates that nothing comes later in this list. Since (cons 'a '()) gives the list (a), this diagram represents (a) as well.

Now consider the list (cons 'b '(a)) or (b a). Here, we draw another rectangle, where the head points to b and the tail points to the representation of (a) that we already have seen. The result is:


Similarly, the list (d c b a) is constructed as
(cons 'd (cons 'c (cons 'b (cons 'a '())))) and would be drawn as follows:

A similar approach may be used for lists, which have components which are sublists. For example, consider the list ((a) b (c d) e) This is a list with four components, so at the top level we will need four rectangles, just as in the previous example for the list (d c b a). Here, however, the first component designates the list (a), which itself involves the box-and-pointer diagram already discussed. Similarly, the list (c d) has two boxes for its two components (just as we discussed for (b a) earlier). The resulting diagram follows:

Additional discussion and examples may be found in the first few pages of Section 11.3 in the textbook.

Throughout these diagrams, the null list is represented by a null pointer or line. Thus, the list containing the null list, ( ( ) ) - that is (cons '() '()) - is represented by a rectangle with lines through both halves:

  1. Draw box-and-pointer diagrams for each of the following lists:
    
       ((x) y z)
       (x (y z))
       ((a) b (c ()))
    
While we consistently have discussed cons in the context of lists, Scheme allows cons to be applied when the second element is not a list. For example, (cons 'a 'b) is a legal expression which can be represented by the following box-and-pointer diagram:

To represent such an expression on paper or as a Scheme printout, dot notation is used: (a . b) Here, the dot indicates that cons has been applied, but the second argument is not a list. Similarly,
(cons 1 'a) may be written (1 . a) and (cons "Henry" "Walker") produces
("Henry" . "Walker"). Using a box-and-pointer representation, this last result would be drawn as follows:

  1. Enter the following into Scheme. In each case, explain when the dot notation appears or why it is not needed.
    
       (cons 'a "Walker")
       (cons 'a '())
       (cons '() 'a)
       (cons '() '())
    
  2. Draw each of the expressions in the previous step using the box-and-pointer representation.

  3. Draw a box-and-pointer representation for the expression
    (this (is) an (exercise (about Scheme)) expressions) .

Association Lists: Consider the organization in a simple telephone book. Overall, a telephone directory consists of a sequence of entries, and each entry in the book includes a name and a telephone number.

One way to write such a directory in Scheme is to consider each entry as a two-element list, such as ("walker" 4208) or ("stone" 3181). An entire directory, then, could be considered as a list of such entries:


   (  ("herman"  4202)  ("stone"   3181)  ("walker"  4208) )
In Scheme, such 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 element of a pair and retrieving the second element of a pair. Thus, the first element of each pair (the car of a pair) often is called a key value, and the remainder of the pair is its associated data. For example, in the above illustration, "herman", "stone", "walker" are the keys, and the numbers are the associated data. As this example suggests, association lists are a simple way to implement small databases.

Since such applications are so common, Scheme provides procedures to retrieve a pair containing a desired key. The most frequently used such procedure is assoc. Given a key and association list, assoc returns the first pair with the given key. If the key does not match any key, then assoc returns false (#f). For example,


   (assoc "stone" '(("herman"  4202) ("stone"   3181) ("walker"  4208)))
returns ("stone" 3181), while .

   (assoc "jepsen" '(("herman"  4202) ("stone"   3181) ("walker"  4208)))
returns #f.

Since such directories typically contain several entries, this is a particularly good circumstance to use a define expression, so a symbol can represent the entire directory:


   (define telephone-directory
      '(  ("herman"  4202)  
          ("stone"   3181)  
          ("walker"  4208) 
       )
   )
With such a definition, (assoc "stone" telephone-directory) returns ("stone" 3181), and (assoc "jepsen" telephone-directory) returns #f.

To find the telephone number corresponding to a given name, we could apply the cadr procedure to the result of assoc:


   (cadr (assoc "stone" telephone-directory))
returns 3181.

  1. Define an association list birthdays which associates peoples' names (as strings) with their birthdays (again, as strings). Thus, a typical entry might be
    ("Lincoln" "February 12, 1809").

  2. Use the assoc procedure to search this association list for someone who is on the list and for someone who is not on the list.

  3. What happens if you search by date instead of by person? (For example, you might try
    (assoc "February 12, 1809" birthdays).)

  4. Add entries so that two people have the same names. Thus, there might be entries
    ("Adams" "October 30, 1735") and ("Adams" "July 11, 1767") for presidents John Adams and John Quincy Adams, respectively. What happens if you try to retrieve a pair with assoc using this common key? (For example, you might try
    (assoc "Adams" birthdays).)

  5. Suppose that the assoc procedure was not built in to Scheme. Write a procedure look-up which accomplishes the same task as assoc.

Note: assoc is actually one of three related precedures in Scheme; the other two procedures 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 lab on predicates to refresh your memory about the details of these predicates.)

  1. Determine the result of each of the following expressions.
    
       (assq 'a '((a 1) (b 2) (c 3)))
       (assq 'b '((a 1) (b 2) (c 3)))
       (assq 'd '((a 1) (b 2) (c 3)))
       (assq (list 'a) '(((a) q) ((b) (r)) ((c))))
       (assoc (list 'a) '(((a) q) ((b) (r)) ((c))))
       (assoc (list 'c) '(((a) q) ((b) (r)) ((c))))
    
    In each case, be sure you can explain why the result is obtained.

This document is available on the World Wide Web as

http://www.math.grin.edu/~walker/courses/151.sp99/lab-pairs.html

created February 21, 1997
last revised February 27, 1999