手続きの抽象化

sicp の1.3.3 と1.3.4 を復習。general Methodと手続きを返す手続きをつかっての手続きの抽象化。題材は主に、平方根で。

[1.3.3 general Methodを使っての抽象化]

指定した手続きの入力と出力の差が十分小さくなくなる時点(fixed point)の入力値を得るための手続き fixed-pointを定義。

(define tolerance 0.00001)
(define (fixed-point f first-guess)
  (define (close-enough? x y)
    (< (abs (- x y) ) tolerance) ) 
  (define (try guess)
    (let ((next (f guess) ) )
       (if (close-enough? next guess)
           next
           (try  next) ) ) ) 
  (try first-guess) )

この手続きを使って。平方根を返す手続きを定義。
算出値の初期値 1.0として
((平方根算出対象の値/前回の算出値) と前回算出値の平均値)の算出を繰り返し実行。 fixed point(前回と今回の算出値の差が十分小さくなる時点)の算出値を平方根の結果とする。

(define (sqrt x)
  (fixed-point (lambda (y) (average y (/ x y) ) ) 1.0) )

[1.3.4 手続きを返す手続き]

手続きを返す手続きを実装することにより、抽象化を行う。
指定した手続きの入力と出力の平均を求める手続きを返す手続き
その手続きを手続きの差が十分小さくなるときの出力値を求める手続き(fixed-point)にわたして平方根をとく
ここでは、以下の3つの手続きを組み合わせていることになる。

      1. x/yを求めるlambda
      2. 指定した手続きの入力と出力の平均を求める手続きを返す手続き(average-dump)
      3. 手続きの入力と結果の差が十分小さくなるときの出力値を求める手続き(fixed-point)
(define (average-dump f)
  (lambda (x) (average x (f x))))

(define (sqrt x)
  (fixed-point (average-dump (lambda (y) (/ x y) ) ) 1.0) )

さらに

さらに、上記の2の目の手続き(average-dump)から1つめの手続き(x/yを求めるlambda)を呼び出すのではなく、それぞれの手続き引数で渡すように抽象化すると。

(define (fixed-point-of-transform g transform guess)
  (fixed-point  (transform g) guess) )

(define (sqrt x)
  (fixed-point-of-transform (lambda (y)  (/ x y) )
                            average-dump