問題1.6

通常版では

(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))