2011/02/23

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 件のコメント: