問題4.69-4.70

続きを。


4.69

(rule ((great . ?rel) ?x ?y)
      (and (son ?x ?z) (?rel ?z ?y)))
(rule ((grandson) ?x ?y)
      (grandson ?x ?y)) 

こうかな。と思って実行してみると、

;;; Query input:
((great grandson) Adam ?x)
;;; Query results:
((great grandson) Adam Irad)

;;; Query input:
((great great grandson) Adam ?x)
;;; Query results:
((great great grandson) Adam Mehujael)

;;; Query input:
((great great great grandson) Adam ?x)
;;; Query results:

でどうやら違う。great二つまでだとちゃんと動くし結果も正しい。だから?relが(great great grandson)に再帰されてないのかな。中の?relの値の変化がみたいなぁ。

...うーん分からない。いろいろ調べてもみんな大体同じ感じにしてあるし。と思ってデータベース眺めてたら

...
(son Irad Mehujael)
(son Mahujael Methushael)
...

というタイポでした。ひどい。直して実行してみると、

;;; Query input:
((great great great grandson) Adam ?x)
;;; Query results:
((great great great grandson) Adam Methushael)

;;; Query input:
((great great great great great grandson) Adam ?x)
;;; Query results:
((great great great great great grandson) Adam Jubal)
((great great great great great grandson) Adam Jabal)

ちゃんと出してくれました。問題文の質問をチェックしてみると

;;; Query input:
((great grandson) ?g ?ggs)
;;; Query results:
((great grandson) Mehujael Jubal)
((great grandson) Irad Lamech)
((great grandson) Mehujael Jabal)
((great grandson) Enoch Methushael)
((great grandson) Cain Mehujael)
((great grandson) Adam Irad)

;;; Query input:
(?r Adam Irad)
;;; Query results:
((great grandson) Adam Irad)
((great great . son) Adam Irad)
((great . grandson) Adam Irad)
. user break

(?r Adam Irad)は終わりません。ついでに最後がgrandsonであることを満たしてません。上の定義はそういえば最後がgrandsonだとチェックすることを忘れてました。なので

(rule ((great . ?rel) ?x ?y)
      (and (?rel ?z ?y) (son ?x ?z) (end-grandson ?rel)))
(rule ((grandson) ?x ?y)
      (grandson ?x ?y))
(rule (end-grandson (grandson)))
(rule (end-grandson (great . ?r))
      (end-grandson ?r))

こうします。すると

;;; Query input:
(?r Adam Irad)
;;; Query results:
((great grandson) Adam Irad)
. user break

終わりません。たぶんどこかでループしてしまうんでしょう。でも最後がgrandsonになるようにはできました。ループ検出器を作ったらちゃんと出してくれるんじゃないかなぁと思います。

4.70

(define ones (cons-stream 1 ones))を思い出そう、と言われたので思い出してみます。

> (define ones (cons-stream 1 ones))
> (stream-ref ones 100)
1
> (stream-ref ones 100000)
1

onesストリームはこういうものでした。問題になってる部分はこれと似てて

(set! THE-ASSERTIONS
      (cons-stream assertion THE-ASSERTIONS))

こうなってます。onesと比較してみれば分かりますが、たぶんこれはTHE-ASSERTIONSがassertionだけをもつストリームになってしまうと思います。実際

> (define twos (cons-stream 2 twos))
> (stream-ref twos 100)
2
> (set! twos (cons-stream 1 twos))
> twos
(1 . #<struct:promise>)
> (stream-ref twos 100)
1

こうなります。でもlet束縛を使うことで

> (let ((old-stream twos))
    (set! twos (cons-stream 1 old-stream)))
> twos
(1 . #<struct:promise>)
> (stream-ref twos 100)
2

このように、もとのストリームを破壊することなくストリームに要素を追加することができます。


ここまで。次は実装の内部を見ていきます。
あとタイトル替えます。SICP解くとかいって他のことやったりしてて、なんかタイトル詐欺のような気がしてきたので。