通常版では
(sqrt 2) ==> 1.41421568627451
new-if版では
==> ERROR: Stack overflow ==> ABORT: (stack-overflow)
ifでは述語がtrueにならない限りelse節が評価されないが、
new-ifはただの手続きのため、呼び出されてすぐにthen節、else節が評価されてしまう。
sqrt-iterではelse節は再帰呼び出しのため、結果として無限ループ→スタックオーバーフローする。
分法要素が驚くほど少ないLispの、ifが特殊形式なのはこのため(ifのような動作をするものをユーザーは作れない)。
Haskellだと遅延評価のために上記のように記述しても問題無く動作する(はずだったと思う)。
↑これで、昔勉強した時にHaskellに感動した覚えあり。
; new-if版のsqrt (define (sqrt x) (sqrt-iter 1.0 x)) (define (sqrt-iter guess x) (new-if (good-enough? guess x) guess (sqrt-iter (improve guess x) x))) (define (new-if predicate then-clause else-clause) (cond (predicate then-clause) (else else-clause))) (define (improve guess x) (average guess (/ x guess))) (define (average x y) (/ (+ x y) 2)) (define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001)) (define (square x) (* x x)) (define (abs x) (if (< x 0) (- x) x))