さかもとのブログ

つらつらと

SICP演習問題4.71

正直言ってここらへんの問題はつまらない...

delay演算を陽に使用しない場合とする場合での違いが一番わかるのは,質問が無限ループになるとき.
つまり,P.276のような場合に振る舞いがおかしくなる.
"無限ループ"なのでもともと正しいものではない

(assert! (married Minnie Mickery))
(assert! (rule (married ?x ?y)
               (married ?y ?x)))
(married Mickery ?who)
simple-queryにdelayを使用する場合
;;; Query results:
(married Mickery Minnie)
(married Mickery Minnie)
(married Mickery Minnie)
(married Mickery Minnie)
:
:

一応結果が表示される.

simple-queryにdelayを使用しない場合
;;; Query input:

何も表示されない.
なぜかというと,delayを使用しない場合,

(define (simple-query query-pattern frame-stream)
  (stream-flatmap
   (lambda (frame)
     (stream-append
      (find-assertions query-pattern frame)
      (apply-rules query-pattern frame))) :<-
   frame-stream))

<-のところの評価が遅延されないために,そこから帰ってこられなくなるから.
apply-rulesでは, apply-a-ruleを呼び出し,apply-a-ruleでは,qevalを呼び出す.
そのqevalで同じquery, frameに対して,simple-queryを呼び出し, 同じループに陥る.
つまり,qeval->simple-query->apply-rules->apply-a-rule->qeval->simple-query->apply-rules->apply-a-rule->....となってしまう.
delayを陽に使わないと,driver-loopのdisplay-streamに帰れないため,何も表示されないまま,ループし続ける.