Page:AIM-453.djvu/34

From Wikisource
Jump to navigation Jump to search
There was a problem when proofreading this page.
Steele and Sussman
32
The Art of the Interpreter

get, see {Note Gaussian}.)

As another example, suppose that George writes MAPCAR, and Harry uses it. Harry complains that MAPCAR is too slow. George then decides to collect some statistics about the use of MAPCAR, such as the number of times called, the average length of the second argument, and so on. He first writes an experimental MAPCAR to count number of calls:

(DEFINE (MAPCAR F L N)
        (CONS (OLDMAPCAR F L) (+ N 1)))

(DEFINE (OLDMAPCAR F L)
        (COND ((NULL L) '())
              (T (CONS (F (CAR L))
                       (OLDMAPCAR F (CDR L))))))

and asks Harry to use it for a while in his program. "I had to add an extra argument to keep track of the count," says George, "and in order to return both the result and the count, I had to cons them together. Please rewrite your program to keep track of the count and pass it on from one call on MAPCAR to the next." Harry's reply is "unprintable".

Now Bruce comes along and asks Harry how to use Harry's program. Harry says, "Just write (DIFFERENTIATE EXP VAR N), where EXP is the expression to be differentiated, VAR is the variable with respect to which to differentiate, and N is George's statistics counter — but that may go away next week." Bruce gives Harry a funny look, then goes away and writes his own DIFFERENTIATE, using George's documentation for the old MAPCAR, of course, unaware that the new one has been installed...

George's new MAPCAR conceptually has state. The state information should be local to the definition of MAPCAR, because that information is not anyone else's business, and George has no business requiring everyone else to keep track of it for him. George and Harry and Bruce all wish George had a way to maintain local state information in MAPCAR.

Side Effects and Local State

Traditionally local state is maintained through some sort of "side effect". We can always avoid the use of side effects if we are willing to pass all state variables around. As we have seen, this requires a monolithic conception of the program structure. If we wish to break a program up into independent modules, each with local state information, we must seek another method.

We claim that any such method effectively constitutes a side effect. If a module has hidden state, then its behavior can potentially change over time.

If only one module in the system has local state, then we can hide the side effect by making it the top-level module of the system, as we have done for DRIVER-LOOP. (For an example of this, see {Note Weber}.) If more than one module has state, however, then each may perceive changes in the