SICP

SICP読書録 #12 1.3.2 lambdaを使って手続きを構築する

hiroshi-manabe様の日本語訳を使わせてもらいます。
練習問題等はGaucheで実行。

前回はこちら

1.3.2 lambdaを使って手続きを構築する

lambdaによって無名の手続きを作ることができる。
これで、以下の手続きを作り直してみよう。

_.scm
(define (pi-sum a b)
  (define (pi-term x)
    (/ 1.0 (* x (+ x 2))))
  (define (pi-next x)
    (+ x 4))
  (sum pi-term a pi-next b))

(define (integral f a b dx)
  (define (add-dx x)
    (+ x dx))
  (* (sum f (+ a (/ dx 2.0)) add-dx b) dx))

pi-term, pi-next, add-dx は内部でのみ利用される手続きだ。いちいちdefineで名前を付ける必要はない。

_.scm
(define (pi-sum a b)
  (sum (lambda (x) (/ 1.0 (* x (+ x 2))))
    a
    (lambda (x) (+ x 4))
    b))

(define (integral f a b dx)
  (* (sum f
          (+ a (/ dx 2.0))
          (lambda (x) (+ x dx))
          b)
      dx))

letを使って局所変数を作る

次の式を計算したい。

f(x,y)=x(x+xy)^2+y(1-y)+(1+xy)(1-y)

これを、以下のように表現しよう。

\begin{align}
a&=1+xy \\
b&=1-y \\
f(x,y)&=xa^2+yb+ab
\end{align}

letを使うと、局所変数を定義できる。これで、以下のように定義できる。

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

練習問題 1.34

次の手続きを定義する。

_.scm
(define (f g) (g 2))

実行してみよう。

_.scm
gosh> (f square)
4 ; (square 2)
gosh> (f (lambda (z) (* z (+ z 1))))
6 ; ((lambda (z) (* z (+ z 1))) 2)

ここで、(f f)という手続きを実行したらどうなるか?
展開してみよう。

_.scm
(f f)
> ((lambda (f g) (g 2) f) 
> (f 2)
> ((lambda (f g) (g 2) 2)
> (2 2)

というわけで、以下のような結果となる。

_.scm
gosh> (f f)
*** ERROR: invalid application: (2 2)