在前面的章節(jié)中,我已經(jīng)講述了如何定義函數(shù)。在本節(jié)中,我講介紹局部變量,這將會(huì)使定義函數(shù)變得更加容易。
使用let
表達(dá)式可以定義局部變量。格式如下:
(let binds body)
變量在binds
定義的形式中被聲明并初始化。body
由任意多個(gè)S-表達(dá)式構(gòu)成。binds
的格式如下:
[binds] → ((p1 v1) (p2 v2) ...)
聲明了變量p1
、p2
,并分別為它們賦初值v1
、v2
。變量的作用域(Scope)為body
體,也就是說變量只在body
中有效。
例1:聲明局部變量
i
和j
,將它們與1
、2
綁定,然后求二者的和。
(let ((i 1) (j 2))
(+ i j))
;Value: 3
let
表達(dá)式可以嵌套使用。
例2:聲明局部變量
i
和j
,并將分別將它們與1
和i+2
綁定,然后求它們的乘積。
(let ((i 1))
(let ((j (+ i 2)))
(* i j)))
;Value: 3
由于變量的作用域僅在body
中,下列代碼會(huì)產(chǎn)生錯(cuò)誤,因?yàn)樵谧兞?code>j的作用域中沒有變量i
的定義。
(let ((i 1) (j (+ i 2)))
(* i j))
;Error
let*
表達(dá)式可以用于引用定義在同一個(gè)綁定中的變量。實(shí)際上,let*
只是嵌套的let
表達(dá)式的語(yǔ)法糖而已。
(let* ((i 1) (j (+ i 2)))
(* i j))
;Value: 3
例3:函數(shù)
quadric-equation
用于計(jì)算二次方程。它需要三個(gè)代表系數(shù)的參數(shù):a
、b
、c
?(ax^2 + bx + c = 0
),返回一個(gè)存放答案的實(shí)數(shù)表。通過逐步地使用let
表達(dá)式,可以避免不必要的計(jì)算。
;;;The scopes of variables d,e, and f are the regions with the same background colors.
(define (quadric-equation a b c)
(if (zero? a)
'error ; 1
(let ((d (- (* b b) (* 4 a c)))) ; 2
(if (negative? d)
'() ; 3
(let ((e (/ b a -2))) ; 4
(if (zero? d)
(list e)
(let ((f (/ (sqrt d) a 2))) ; 5
(list (+ e f) (- e f)))))))))
(quadric-equation 3 5 2) ; solution of 3x^2+5x+2=0
;Value 12: (-2/3 -1)
這個(gè)函數(shù)的行為如下:
- 如果二次項(xiàng)系數(shù)
a
為0
,函數(shù)返回'error
。- 如果
a ≠ 0
,則將變量d
與判別式(b^2 - 4ac)
的值綁定。- 如果
d
為負(fù)數(shù),則返回'()
。- 如果
d
不為負(fù)數(shù),則將變量e
與-b/2a
綁定。- 如果
d
為0
,則返回一個(gè)包含e
的表。- 如果
d
是正數(shù),則將變量f
與√(d/2a)
綁定,并返回由(+ e f)
和(- e f)
> 構(gòu)成的表。
實(shí)際上,let
表達(dá)式只是lambda
表達(dá)式的一個(gè)語(yǔ)法糖:
(let ((p1 v1) (p2 v2) ...) exp1 exp2 ...)
;?
((lambda (p1 p2 ...)
exp1 exp2 ...) v1 v2)
這是因?yàn)?code>lambda表達(dá)式用于定義函數(shù),它為變量建立了一個(gè)作用域。
練習(xí)1
編寫一個(gè)解決第四章練習(xí)1的函數(shù),該函數(shù)旨在通過一個(gè)初始速度
v
和與水平面所成夾角a
來計(jì)算飛行距離。
本節(jié)中,我介紹了let
表達(dá)式,let
表達(dá)式是lambda
表達(dá)式的一個(gè)語(yǔ)法糖。變量的作用域通過使用let
表達(dá)式或lambda
表達(dá)式來確定。在Scheme中,這個(gè)有效域由源代碼的編寫決定,這叫做詞法閉包(lexical closure)。
(define (throw v a)
(let ((r (/ (* 4 a (atan 1.0)) 180)))
(/ (* 2 v v (cos r) (sin r)) 9.8)))
更多建議: