(lambda (x) (+ x 4))とか
(lambda (x) (/ 1.0 (* x (+ x 2))))と書ける. そうするとpi-sumは補助の手続きを定義せずに
(define (pi-sum a b) (sum (lambda (x) (/ 1.0 (* x (+ x 2)))) a (lambda (x) (+ x 4)) b))と書ける.
またlambdaを使うと, 補助の手続きadd-dxを定義せずに
(define (integral f a b dx) (* (sum f (+ a (/ dx 2.0)) (lambda (x) (+ x dx)) b) dx))と書ける.
一般的にlambdaは, 手続きに名前がつかない他は, defineと同様に手続きを作り出すのに使う.
(lambda (〈formal-parameters〉) 〈body〉)で出来上る手続きはdefineで作られたものと全く同じ手続きである. 唯一の相違は環境で名前と対応づけられていないことである. 実際
(define (plus4 x) (+ x 4))は
(define plus4 (lambda (x) (+ x 4)))と等価である. lambda式は次のように読める:
(lambda (x) (+ x 4)) ↑ ↑ ↑ ↑ ↑ 手続き xを引数とする を足す x と 4
((lambda (x y z) (+ x y (square z))) 1 2 3) 12のような組合せや, また更に一般に通常は手続き名を使う文脈で演算子として使える.53
(define (f x y) (define (f-helper a b) (+ (* x (square a)) (* y b) (* a b))) (f-helper (+ 1 (* x y)) (- 1 y)))
もちろん局所変数の束縛には名なしの手続きを指定するためのlambda式が使える. fの本体はその手続きの呼出しだけとなる:
(define (f x y) ((lambda (a b) (+ (* x (square a)) (* y b) (* a b))) (+ 1 (* x y)) (- 1 y)))この形は有用なので, letという特殊形式が更に便利に使えるようにしている. letを使うとf手続きは
(define (f x y) (let ((a (+ 1 (* x y))) (b (- 1 y))) (+ (* x (square a)) (* y b) (* a b))))と書ける. letの一般形は
(let | (〈var1〉 | 〈exp1〉) |
(〈var2〉 | 〈exp2〉) | |
(〈varn〉 | 〈expn〉)) |
この等価関係からlet式で指定された変数の有効範囲は, letの本体であることが分る. つまり:
• letは変数をそれが使われる場所に出来るだけ局所的に束縛する. 例えばxの値が5なら, 式
(+ (let ((x 3)) (+ x (* x 10))) x)の値は38である. letの本体でxは3で, let式の値は33. 一方外側の+の第二引数のxはまだ5である.
(let ((x 3) (y (+ x 2))) (* x y))の値は, letの本体内でxは3で, (外側のx足す2の)y は4だから, 12になる.
時にはletと同じ効果を得るため内部定義を使うことがある. 例えば上の手続きfを
(define (f x y) (define a (+ 1 (* x y))) (define b (- 1 y)) (+ (* x (square a)) (* y b) (* a b)))と定義してもよかった. しかし内部defineは内部手続きのためだけにし, このような状況ではletを使いたい.54
(define (f g) (g 2))を定義したとする. その時
(f square) 4 (f (lambda (z) (* z (+ z 1)))) 6解釈系に組合せ(f f)を(意地悪く)評価させるとどうなるか. 説明せよ.
53
Lispを学ぶ人にはlambdaより, make-procedureのようなもっと明白な名前であったら, ずっとわかりやすく,強迫感も少かったろう. しかしこの習慣は強固に防護されている. この記法は数理論理学者
Alonzo Church(1941)の数学形式論,
λ算法から取り込まれた. Churchは関数と関数作用の概念を研究するための厳密な基盤としてλ計算を考え出した. λ計算はプログラム言語の意味論を数学的に研究する基本的道具になっている.
54
プログラムがわれわれの意味していると思うことを意味していることが確かである程に内部定義を十分理解するには, 本節で述べた評価のプロセスより精巧なモデルが必要である. 手続きの内部定義ではこの微妙さは生じない. 評価について更に学んだ後,
4.1.6節でこの問題に戻ることにする.