Many uses of abstract functions require the definition of auxiliary
functions. Consider filter1
, which consumes a filtering function,
a list, and a filtering item. In the previous section alone, we
encountered three uses of filter1
with three different auxiliary
functions: squared?
, <_{ir}
, and eqir?
.
Since these auxiliary functions are only used as arguments to
filter1
, we should employ the program organization guidelines
from the preceding intermezzo (18). That is, we should
use a localexpression to indicate that the application of
filter1
and the auxiliary function definition belong together.
Here is one possible arrangement for the filter1
eqir?
combination:
;; find : listofIRs symbol > boolean
(define (find aloir t)
(local ((define (eqir? ir p)
(symbol=? (irname ir) p)))
(filter1 eqir? aloir t)))
An alternative arrangement places the localexpression where the function is needed:
;; find : listofIRs symbol > boolean
(define (find aloir t)
(filter1 (local ((define (eqir? ir p)
(symbol=? (irname ir) p)))
eqir?)
aloir t))
This alternative is feasible because the names of functions  like
eqir?
 are now legitimate expressions and can play the
role of local
's body. Thus the localexpression
introduces a function definition and returns the function as its result.
Because good programmers use abstract functions and organize their programs
in a tidy manner, it is not surprising that Scheme provides a shorthand
for this particular, frequent use of local
. The shorthand is
called a lambdaexpression and greatly facilitates the
introduction of functions like eqir?
, squared?
, or
<_{ir}
. The following two subsections introduce the syntax and
semantics of lambdaexpressions. The last subsection discusses
its pragmatics.
A lambdaexpression is just a new form of expression:

Here are three useful examples:
(lambda (x c) (> (* x x) c))
(lambda (ir p) (< (irprice ir) p))
(lambda (ir p) (symbol=? (irname ir) p))
They correspond to squared?
, <_{ir}
, and eqir?
,
respectively, the three motivating examples discussed above.
A lambdaexpression defines an anonymous function, that is, a function without a name. The sequence of variables behind lambda are the function's parameters; the third component is the function's body.
As discussed in the introduction, a lambdaexpression is just a shorthand for a localexpression. In general, we can think of
(lambda (x1 ... xn) exp) 
(local ((define (anewname x1 ... xn) exp)) anewname) 
anewname
, may not occur in
exp
.The shorthand explanation suggests that
(lambda (x1 ... xn) exp) 
x1
...xn
as binding occurrences and that
the scope of parameters is exp
. Of course, if exp
contains
further binding constructs (say, a nested localexpression), then
the scope of the variables may have a hole. Similarly, the explanation implies basic facts that govern the evaluation of lambdaexpressions:
A lambdaexpression is a value because functions are values.
The application of lambdaexpressions to values proceeds according to our usual laws of function application, assuming we expand the shorthand first.
Here is a sample use of lambda
:
(filter1 (lambda (ir p) (< (irprice ir) p)) (list (makeir 'doll 10)) 8)
The application of filter1
consumes the
lambdaexpression, a (short) list of inventory records, and a
threshold. Given our suggestion, the evaluation
can be understood by an
expansion of the lambdaexpression into a corresponding
localexpression:
... = (filter1 (local ((define (<_{ir} ir p) (< (irprice ir) p))) <_{ir}) (list (makeir 'doll 10)) 8) = (filter1 <_{ir} (list (makeir 'doll 10)) 8)
For the last step, the local definition of <_{ir}
is lifted and
added to the toplevel definitions. From here, the evaluation proceeds
as in section 19.2.
While it is natural to think of lambda
as a shorthand, the last
two points also suggest a way of understanding lambdaexpressions
directly. In particular, we can adapt the law of application to
lambdaexpressions:
((lambda (x1 ... xn) exp) val1 ... valn)  = exp with all occurrences of 
Let us reconsider the above example in this light:
(filter1 (lambda (ir p) (< (irprice ir) p))
(list (makeir 'doll 10))
8)
As usual, this application is replaced by the body of filter1
with all parameters replaced by their values. This step places a
lambdaexpression into the function position of an application:
= (cond
[((lambda (ir p) (< (irprice ir) p))
(makeir 'doll 10) 8)
(cons (first (list (makeir 'doll 10)))
(filter1 (lambda (ir p) (< (irprice ir) p))
(rest (list (makeir 'doll 10)))
8))]
[else
(filter1 (lambda (ir p) (< (irprice ir) p))
(rest (list (makeir 'doll 10)))
8)])
= (cond
[(< (irprice (makeir 'doll 10)) 8)
(cons (first (list (makeir 'doll 10)))
(filter1 (lambda (ir p) (< (irprice ir) p))
(rest (list (makeir 'doll 10)))
8))]
[else
(filter1 (lambda (ir p) (< (irprice ir) p))
(rest (list (makeir 'doll 10)))
8)])
= ...
From here, the evaluation proceeds as usual. Still, even this shorthand evaluation shows that, while using lambdaexpressions in programs is convenient, replacing it with a named function (often) simplifies calculations.
Exercise 24.0.7. Decide which of the following phrases are legal lambdaexpressions:
(lambda (x y) (x y y))
(lambda () 10)
(lambda (x) x)
(lambda (x y) x)
(lambda x 10)
Explain why they are legal or illegal. Solution
Exercise 24.0.8.
Draw arrows from the underlined occurrences of x
to their binding
occurrences in each of the following three lambdaexpressions:
(lambda (x y) (+ x (* x y)))
(lambda (x y) (+ x (local ((define x (* y y))) (+ (* 3 x) (/ 1 x)))))
(lambda (x y) (+ x ((lambda (x) (+ (* 3 x) (/ 1 x))) (* y y))))
Also draw a box for the corresponding scope of each underlined x
and holes in the scope where necessary.
Solution
Exercise 24.0.9. Evaluate the following expressions by hand:
((lambda (x y) (+ x (* x y))) 1 2)
((lambda (x y) (+ x (local ((define x (* y y))) (+ (* 3 x) (/ 1 x))))) 1 2)
((lambda (x y) (+ x ((lambda (x) (+ (* 3 x) (/ 1 x))) (* y y)))) 1 2)
The guideline for using lambdaexpressions is straightforward:
Guideline on Lambda Expressions 
Use lambdaexpressions when a function is not recursive and is only needed once in an argument position. 
If we were to apply the guideline to the programs in the preceding
sections, we would quickly see how much lambda
simplifies the use
of abstracted functions. For that reason, Scheme offers many abstracted
functions in its libraries. In future sections, we will encounter many
more examples where lambdaexpressions are convenient.