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))
を期待してたんだけど
もしかしてassv
をassoc
にしたのが影響してる?
どう影響するんだっけ
わからんけど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が出力した結果をそのまま使えないのが面倒だけど