計算機プログラムの構造と解釈

  • 1.5

この前微妙な感じで終わってしまった。
自分でも良くわからなかったので、何とか納得できる形に説明してみる。

(define (p) (p))

(define (test x y)
  (if (= x 0)
      0
      y))

(test 0 (p))

;;普通にMzSchemeで実行すると無限ループになった。

作用的順序と正規順序について復習
作用的順序評価では、関数を実行する時点で、値が被演算子が評価され値が呼ばれる。
よって、

(test 0 (p))

の時点で(p)を求めようとし、再帰の無限ループに入ってしまう。
一方、正規順序評価では、必要になるまで実際の値を求めようとはしない。
また、ifはスペシャルフォームなので、必要な引数に対してしか評価を実行しない。

(test 0 (p));;この時点では下に流れる。
(if (= 0 0) 0 (p));;ifの結果では、初めの「0」が呼び出される。
;;ifは真になる条件以外の計算を省くため、(p)が実際呼び出されることはない。

こんな感じだろうか?

  • 1.6

上と同じ感じに1.6もとける。

(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)))
;;普通にMzSchemeで実行すると無限ループになった。

上と同じで、defineで関数として定義したため、被演算子は宣言時点で評価されてしまう。
この例でいうと、

(sqrt-iter (improve guess x)
           x)))

の部分が再帰となっており、宣言時点で評価されてしまうため、無限ループに入った。
その点、ifはスペシャルフォームのため、評価は行われない。


今日はつかれたのでここまで。