Structure and Interpretation of Computer Programs



Yüklə 2,71 Mb.
Pdf görüntüsü
səhifə27/222
tarix08.08.2018
ölçüsü2,71 Mb.
#61085
1   ...   23   24   25   26   27   28   29   30   ...   222

The resulting procedure is just as much a procedure as one that is created using 

define


. The 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 a 

lambda

 expression 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, a 

lambda

 expression 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 procedure name.

53

Using 

let

 to create local variables

Another use of 

lambda

 is in creating local variables. We often need local variables in our procedures



other than those that have been bound as formal parameters. For example, suppose we wish to

compute the function

which we could also express as 

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 a 

lambda

 expression to specify an anonymous procedure for binding our



local variables. The body of 

f

 then 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)))

This construct is so useful that there is a special form called 

let

 to make its use more convenient.



Using 

let


, the 

f

 procedure could be written as



(define (f x y)

  (let ((a (+ 1 (* x y)))

        (b (- 1 y)))

    (+ (* x (square a))

       (* y b)

       (* a b))))

The general form of a 

let


 expression is

(let ((<var



1

> <exp



1

>)

      (<var



2

> <exp



2

>)

      



      (<var

n

> <exp



n

>))


   <body>)

which can be thought of as saying

let 

<var

1

> have the value <exp



1

> and


<var

2

> have the value <exp



2

> and


<var

n

> have the value <exp



n

>

in 



<body>

The first part of the 

let

 expression is a list of name-expression pairs. When the 



let

 is evaluated,

each name is associated with the value of the corresponding expression. The body of the 

let


 is

evaluated with these names bound as local variables. The way this happens is that the 

let

 expression



is interpreted as an alternate syntax for

((lambda (<var



1

> ...<var

n

>)

    <body>)



 <exp

1

>

 



 <exp

n

>)




No new mechanism is required in the interpreter in order to provide local variables. A 

let


 expression

is simply syntactic sugar for the underlying 

lambda

 application.



We can see from this equivalence that the scope of a variable specified by a 

let


 expression is the

body of the 

let

. This implies that:



Let

 allows one to bind variables as locally as possible to where they are to be used. For example,

if the value of 

x

 is 5, the value of the expression



(+ (let ((x 3))

     (+ x (* x 10)))

   x)

is 38. Here, the 



x

 in the body of the 

let

 is 3, so the value of the 



let

 expression is 33. On the

other hand, the 

x

 that is the second argument to the outermost 



+

 is still 5.

The variables’ values are computed outside the 

let


. This matters when the expressions that

provide the values for the local variables depend upon variables having the same names as the

local variables themselves. For example, if the value of 

x

 is 2, the expression



(let ((x 3)

      (y (+ x 2)))

  (* x y))

will have the value 12 because, inside the body of the 

let



x



 will be 3 and 

y

 will be 4 (which is



the outer 

x

 plus 2).



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

let


. For example, we could

have defined the procedure 

f

 above 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 use 

let


 in situations like this and to use internal 

define


 only for internal 

procedures.

54

Exercise 1.34.  Suppose we define the procedure

(define (f g)

  (g 2))

Then we have

(f square)

4

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



6


Yüklə 2,71 Mb.

Dostları ilə paylaş:
1   ...   23   24   25   26   27   28   29   30   ...   222




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə