• 沒有找到結果。

Constructing Procedures Using lambda

在文檔中 second edition (頁 111-117)

Building Abstractions with Procedures

1.3 Formulating Abstractions with Higher-Order Procedureswith Higher-Order Procedures

1.3.2 Constructing Procedures Using lambda

In usingsumas in Section 1.3.1, it seems terribly awkward to have to define trivial procedures such aspi-termandpi-nextjust so we can use them as arguments to our higher-order procedure. Rather than de-finepi-nextandpi-term, it would be more convenient to have a way to directly specify “the procedure that returns its input incremented by 4” and “the procedure that returns the reciprocal of its input times its input plus 2.” We can do this by introducing the special formlambda, which creates procedures. Usinglambdawe can describe what we want as

(lambda (x) (+ x 4))

and

(lambda (x) (/ 1.0 (* x (+ x 2))))

en ourpi-sumprocedure can be expressed without defining any aux-iliary procedures as

(define (pi-sum a b)

(sum (lambda (x) (/ 1.0 (* x (+ x 2)))) a

(lambda (x) (+ x 4)) b))

Again usinglambda, we can write theintegralprocedure without hav-ing to define the auxiliary procedureadd-dx:

(define (integral f a b dx) (* (sum f

(+ a (/ dx 2.0)) (lambda (x) (+ x dx)) b)

dx))

In general, lambda is used to create procedures in the same way as

define, except that no name is specified for the procedure:

(lambda (formal-parameters) body)

e resulting procedure is just as much a procedure as one that is cre-ated usingdefine. e only difference is that it has not been associated with any name in the environment. In fact,

(define (plus4 x) (+ x 4))

is equivalent to

(define plus4 (lambda (x) (+ x 4)))

We can read alambdaexpression as follows:

(lambda (x) (+ x 4))

| | | | |

the procedure of an argument x that adds x and 4

Like any expression that has a procedure as its value, alambda expres-sion can be used as the operator in a combination such as

((lambda (x y z) (+ x y (square z))) 1 2 3)

12

or, more generally, in any context where we would normally use a pro-cedure name.53

53It would be clearer and less intimidating to people learning Lisp if a name more obvious thanlambda, such asmake-procedure, were used. But the convention is firmly entrenched. e notation is adopted from the λ-calculus, a mathematical formalism in-troduced by the mathematical logician AlonzoChurch (1941). Church developed the λ-calculus to provide a rigorous foundation for studying the notions of function and function application. e λ-calculus has become a basic tool for mathematical investi-gations of the semantics of programming languages.

Usingletto create local variables

Another use oflambdais in creating local variables. We oen need lo-cal variables in our procedures other than those that have been bound as formal parameters. For example, suppose we wish to compute the function

f (x, y) = x(1 + xy)2+ y(1− y) + (1 + xy)(1 − y), which we could also express as

a= 1 + xy, b = 1 − y,

f (x, y) = xa2+ yb + ab.

In writing a procedure to compute f , we would like to include as local variables not only x and y but also the names of intermediate quantities like a and b. One way to accomplish this is to use an auxiliary procedure to bind the local variables:

(define (f x y)

(define (f-helper a b) (+ (* x (square a))

(* y b) (* a b)))

(f-helper (+ 1 (* x y)) (- 1 y)))

Of course, we could use alambdaexpression to specify an anonymous procedure for binding our local variables. e body offthen becomes a single call to that procedure:

(define (f x y) ((lambda (a b)

(+ (* x (square a)) (* y b)

(* a b))) (+ 1 (* x y)) (- 1 y)))

is construct is so useful that there is a special form calledletto make its use more convenient. Usinglet, thefprocedure could be wrien as

(define (f x y)

(let ((a (+ 1 (* x y))) (b (- 1 y))) (+ (* x (square a))

(* y b) (* a b))))

e general form of aletexpression is

(let ((var1⟩ ⟨exp1) (var2⟩ ⟨exp2) . . .

(varn⟩ ⟨expn))

body)

which can be thought of as saying

let var1 have the value exp1 and

var2 have the value exp2 and . . .

varn have the value expn in body

e first part of theletexpression is a list of name-expression pairs.

When theletis evaluated, each name is associated with the value of the corresponding expression. e body of the let is evaluated with these names bound as local variables. e way this happens is that the

letexpression is interpreted as an alternate syntax for

((lambda (var1 . . . varn)

body)

exp1 . . .

expn)

No new mechanism is required in the interpreter in order to provide local variables. Aletexpression is simply syntactic sugar for the un-derlyinglambdaapplication.

We can see from this equivalence that the scope of a variable spec-ified by aletexpression is the body of thelet. is implies that:

letallows one to bind variables as locally as possible to where they are to be used. For example, if the value ofxis 5, the value of the expression

(+ (let ((x 3)) (+ x (* x 10))) x)

is 38. Here, thexin the body of theletis 3, so the value of the

letexpression is 33. On the other hand, thexthat is the second argument to the outermost+is still 5.

• e variables’ values are computed outside thelet. is maers when the expressions that provide the values for the local vari-ables depend upon varivari-ables having the same names as the local variables themselves. For example, if the value of xis 2, the ex-pression

(let ((x 3)

(y (+ x 2))) (* x y))

will have the value 12 because, inside the body of thelet,xwill be 3 andywill be 4 (which is the outerxplus 2).

Sometimes we can use internal definitions to get the same effect as with

let. For example, we could have defined the procedurefabove as

(define (f x y)

(define a (+ 1 (* x y))) (define b (- 1 y)) (+ (* x (square a))

(* y b) (* a b)))

We prefer, however, to useletin situations like this and to use internal

defineonly for internal procedures.54

Exercise 1.34:Suppose we define the procedure

(define (f g) (g 2))

en we have

(f square) 4

(f (lambda (z) (* z (+ z 1)))) 6

What happens if we (perversely) ask the interpreter to eval-uate the combination(f f)? Explain.

54Understanding internal definitions well enough to be sure a program means what we intend it to mean requires a more elaborate model of the evaluation process than we have presented in this chapter. e subtleties do not arise with internal definitions of procedures, however. We will return to this issue inSection 4.1.6, aer we learn more about evaluation.

在文檔中 second edition (頁 111-117)