PAIProlog
Paradigms of Artificial Intelligence Programming (実用 Common Lisp) のコードに Christophe Rhodes さんが手を入れて PAIProlog として公開されている。
それに Allegro Prolog の <--
と prolog
を実装してみた。すでにどこかにありそうなんだけどなぁ。。。と思いつつ。
<--
は同じ名前かつ同じ引数の数のものを再定義する。
prolog
は Common Lisp から Prolog を使うためのマクロ。次のように lisp/2 経由で Common Lisp の変数にアクセスできる。
(let ((x 100) y)
(prolog (lisp ?a x)
(= ?a ?b)
(lisp ? (setf y (+ ?b ?b x 1))))
y)
;;=> 301
ソースは github に https://github.com/quek/paiprolog
prolog
の方の実装は2重バッククオートを使った複雑なコードになってしまった。レキシカル変数にアクセスするためにマクロ展開時にクロージャを作るようにしたけど、もっと簡単に書けないかな?
(defun insert-deref (exp)
(if (atom exp)
(if (variable-p exp)
`(deref ,exp)
exp)
(cons (insert-deref (car exp))
(insert-deref (cdr exp)))))
(defun prolog-translate-goals (goals)
(mapcar (lambda (goal)
(if (starts-with goal 'lisp)
(let ((vars (variables-in (last goal))))
``(,@',(butlast goal)
(apply ,(lambda (,@vars)
,@(insert-deref (last goal)))
,',vars)))
`',goal))
goals))
(defmacro prolog (&rest goals)
"Run Prolog in the surrounding Lisp environment
which is accessed from lisp functor.
(let ((x 100) y)
(prolog (lisp ?a x)
(= ?a ?b)
(lisp ? (setf y (+ ?b ?b x 1))))
y)
;;=> 301
"
(let ((goals (replace-?-vars goals)))
`(block prolog
(clear-predicate 'top-level-query)
(add-clause `((top-level-query)
,,@(prolog-translate-goals goals)))
(run-prolog 'top-level-query/0 #'ignore))))
0 件のコメント:
コメントを投稿