Steele and Sussman

22

The Art of the Interpreter

scoping is a valuable technique for producing modularity, but we see no virtue at all in the confusion produced by quoted LAMBDA-expressions. While quoted LAMBDA-expressions do produce dynamic scoping, the support of dynamic scoping does not depend on the quotation of LAMBDA-expressions.)

While lexical scoping solves our problems of referential transparency, we will see later that we must in turn pay a large price for it — but it is not a price of run-time efficiency (contrary to popular belief)!

```
(DEFINE (EVAL EXP ENV)
(COND ((ATOM EXP)
(COND ((NUMBERP EXP) EXP)
(T (VALUE EXP ENV))))
((EQ (CAR EXP) 'QUOTE)
(CADR EXP))
((EQ (CAR EXP) 'LAMBDA)
(LIST '&PROCEDURE (CADR EXP) (CADDR EXP) ENV))
((EQ (CAR EXP) 'COND)
(EVCOND (CDR EXP) ENV))
(T (APPLY (EVAL (CAR EXP) ENV)
(EVLIS (CDR EXP) ENV)))))
(DEFINE (APPLY FUN ARGS)
(COND ((PRIMOP FUN) (PRIMOP-APPLY FUN ARGS))
((EQ (CAR FUN) '&PROCEDURE)
(EVAL (CADDR FUN)
(BIND (CADR FUN) ARGS (CADDDR FUN))))
(T (ERROR))))
```

For VALUE and BIND see Figure 3.

For EVCOND and EVLIS see Figure 5.

Figure 7

Evaluator for Lexically Scoped LAMBDA-notation

Let's see what we have bought. One thing we can do is generalize MAPCAR. After yet more programming experience we find that we write many MAPCAR-like procedures. For example, we might need a kind of MAPCAR where the function F always returns a list, and we want to produce not a list of the lists, but the concatenation of the lists. We might also want to take the sum or the product of all the numbers in a list, or the sum of the cars of all elements in a list. The general pattern is that we look at each element of a list, do something to it, and then somehow combine the results of all these elementwise operations. Another application might be to check for duplicates in a list; for each element we want to see whether another copy follows it in the list. We further generalize the pattern to look at successive trailing segments of the list; we can always take the car to