kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

Reasoned Schemer (82) appendo

appendooutに結果をunifyするだけだから動き的に新しいところはない、かな?

(defrel (appendo l t out)
  (conde
    ((nullo l) (== t out))
    ((fresh (a d res)
       (conso a d l)
       (appendo d t res)
       (conso a res out)))))

たとえば

> (run 3 x (fresh (y z) (appendo x y z)))
'(()
  (_0)
  (_0 _1))

(appendo x y z)
まず(nullo x)からx()になる
次は(appendo d t res)から(nullo t)t()になってres()になってout`(,a)になる
あとは繰り返し

しばらくcakeとかice creamとかで遊ぶ
たくさん例があるんだけれどもひとつひとつの例で何を言おうとしているんだろうか
考えながら見直してみる

> (run* x (fresh (y) (appendo `(cake ,y) '(tastes yummy) x)))
'((cake _0 tastes yummy))

yは何も言われないうちにcarに入って消えてしまうのでfreshなまま
yはなんでもいいよ、という答えがひとつだけ出る

> (run 3 x (fresh (y) (appendo `(cake . ,y) '(d t) x)))
'((cake d t) (cake _0 d t) (cake _0 _1 d t))

,yの前に.がついたら答えが複数出るように
これは再帰していくと(appendo y '(d t) x)という形で評価されるようになり
(nullo y)を満たすyを探すため
run*にするとそういうyがいくらでも見つかるので帰ってこない

という理解でよいでしょうか!