一人読書会 「計算機プログラムの構造と解釈」 (3)
1.1.7 Newton 法による平方根
Newton法 により平方根を求める手続きを実装する。
問題 1.6
ifは特殊形式であるが、cond を利用して普通の手続きとして定義し、平方根の計算にこれを使おうとすると何が起きるか。
以下、特殊形式の if を 通常の手続きである、new-if を定義し、平方根を Newton法 で求める処理を書き直した。
(define (square x) (* x x)) (define (sqrt-itr guess x) (new-if (good-enugh? guess x) guess (sqrt-itr (improve guess x) x))) (define (improve guess x) (avarage guess(/ x guess))) (define (avarage x y) (/ (+ x y) 2)) (define (good-enugh? guess x) (< (abs (- (square guess) x)) 0.001)) (define (sqrt2 x) (sqrt-itr 1.0 x)) (define (new-if predicate then-clause else-clause) (cond (predicate then-clause) (else else-clause)))
実際に動かしてみると、スタックオーバーフローだろう、Out Of Memory が発生した。
特殊形式 if を使った場合には、想定通りの動きをしていた。ぱっと見、等価に思えるが。
うーーん 。。。 なぜだろう 。。。
・・・
特殊形式・・・ define は 特殊形式で、作用は行わない。。。 if も特殊形式・・・
通常評価は、部分式を評価し、作用(演算子を適用)させる・・・
おお!そうか、特殊形式ではないから、被演算子がすべて評価されてしまうからか!、sqrt-itr の else 節 で、再帰しているのが、終了条件に合致しても、else節 がなんと、評価されてしまうのだ!
if は特殊形式で、条件に合致した then または、 else のどちらかしか評価しないのだ。
なるほど。