kb84tkhrのブログ

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

Reasoned Schemer (73) conj2 続き

> (run* q (conj2 (== 'corn q) (== 'meal q)))
'()

これはどういう動きか

  ((conj2 (== 'corn q) (== 'meal q)) empty-s)
= (append-map-inf (== 'meal q) ((== 'corn q) empty-s))
= (append-map-inf (== 'meal q) '(((#(q) . corn))))
= (append-inf ((== 'meal q) `((#(q) . corn)) '()))

ここで(unify 'meal q ``((#(q) . corn)))の結果が、えーと#fになるのかな
(walk u s)'meal(walk v s)corn
うん#f
((== 'meal q) ``((#(q) . corn))()になると

> (run* q (conj2 (== 'corn q) (== 'corn q)))
'(corn)

こっちはほぼ同じで(unify 'corn q ``((#(q) . corn)))'((#(q) . corn))
だいたいわかったな
ついでにもうひとつやってみよう

> (run* (p q) (conj2 (== 'corn p) (== 'meal q)))
'()

あれ
おかしいな
'((corn meal))を期待してたんだけど

もしかしてassvassocにしたのが影響してる?
どう影響するんだっけ
わからんけどassvに戻してやってみる

> (run* (p q) (conj2 (== 'corn p) (== 'meal q)))
'((corn meal))

mjk

assocでもconj2まではちゃんと動く

> ((conj2 (== 'corn p) (== 'meal q)) empty-s)
'(((#(q) . meal) (#(p) . corn)))

じゃあrunのあたりだな
マクロを展開するとこんな感じ(conjは省略)

(let ((q (var 'q)))
  (map (reify q)
     (run-goal #f
        (fresh (p q) (== `(,p ,q) q) (conj2 (== 'corn p) (== 'meal q))))))

(== ``(,p ,q) q)
このふたつのqは別物になってくれないとダメなんだよな
やっぱassvじゃないとダメか
てことは結局'((#(q) . corn)))じゃなくて``((,q . corn)))て書かなきゃいけないのか
いやそれでもうまく動かせないんだっけか

assvだとREPLでうまくいかない例はこんな感じ

> (append-map-inf (== 'meal q) '(((#(q) . corn))))
'(((#(q) . meal) (#(q) . corn)))

バッククォートで書き直すと

> (append-map-inf (== 'meal q) `(((,q . corn))))
'()

大丈夫かな
REPLが出力した結果をそのまま使えないのが面倒だけど