1.3.2 lambdaを使う手続きの構築

文責:@naoiwata

本節では lambda 式と let 式を学ぶ. どちらも特殊形式の構文である.

lambda 式 (lambda (<parameters>) <body>)

一般的に手続きに名前がつかない他は define と同様に手続きを作り出すのに使う.

この lambda 式は手続きへと評価される. lambda 式が評価される時に有効な環境は, その手続きの一部として保存される. 後からこの手続きを実引数と共に呼び出すと, lambda 式が評価された時の環境が仮引数の各変数を新しい場所へと束縛することによって拡張され, 対応する実引数値がそれらの場所に格納される. そしてlambda 式の本体の各式がその環境の中で逐次的に評価される. そして, 最後の式の結果がその手続きの結果として返される.

let 式 (let ((var1 exp1) (var2 exp2 ...)) <body>)

let 式は仮引数として束縛されたもの以外にも手続きに局所的な変数を使いたい場合使える. let 式は lambda 作用の構文糖衣である. let 式で指定された変数の有効範囲(以下, 環境と呼ぶ)は let の本体になる.

let 式はまず束縛部の各初期値が全て評価され, 変数が束縛される. 変数はその結果を保持する新しい環境へ束縛されており, その環境の中で <本体> が評価される.

lambda 式と let 式を使った例

関数 \(f(x, y) = x(1 + xy)^2 + y(1 - y) + (1 + xy)(1 - y)\) を計算する場合を考える.

\(a = 1 + xy\)
\(b = 1 - y\)

と置き換えると, \(f(x, y) = xa^2 + yb + ab\) と書ける. これを計算したい場合以下のように定義できる.

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

これを a, b という局所変数を lambda 式を使って定義すると以下のように置き換えられる.

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

また, let 式を使うことで更に抽象化できる.

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