SICP 問題1.6の解答

読書会のメンバーmahata氏を見習って、解答の一部をアップしてみることにしました。まずは問題1.6の解答です。

new-ifの評価が始まる前に引数が評価され、その中でsqrt-iter再帰呼び出しされているので無限ループになる。

解答の説明をする前にまずは、この問題でとりあげている関数の定義を以下に示します。

(define (new-if predicate then-clause else-clause)
        (cond
                (predicate then-clause)
                (else else-clause)
        )
)
(define (sqrt-iter guess x)
        (new-if (good-enough? guess x)
                guess
                (sqrt-iter (improve guess x)
                        x)
        )
)

次に、(sqrt-iter 1.0 2)を例に、実際にnew-ifの評価がいつまでも始まらない様子をステップごとに見て行きます。(説明に不要なステップは飛ばしてます)

(sqrt-iter 1.0 2)
=>
(new-if (good-enough? 1.0 2)
        1.0
        (sqrt-iter (improve 1.0 2) 2)
)
=>
(new-if #f ;; (good-enough? 1.0 2)を評価
        1.0
        (sqrt-iter 1.5 2) ;;(improve 1.0 2)を評価したが、sqrt-iterをまだ評価できるのでnew-ifの評価に進まない
) 
=>
(new-if #f ;; 
        1.0
        (new-if #f ;; (good-enough? 1.5 2)を評価
                1.5
                (sqrt-iter 1.4166666666666665 2) ;;(improve 1.5 2)を評価するが、sqrt-iterがまだ評価出来る...以下ループ
        )
)

処理系ごとの評価戦略の違いを意識させられる問題でした。引数渡しの方法については、五十嵐先生のページが詳しくて参考になりました。