Reasoned Schemer (82) appendo
appendo
はout
に結果を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
がいくらでも見つかるので帰ってこない
という理解でよいでしょうか!