ラベル Prolog の投稿を表示しています。 すべての投稿を表示
ラベル Prolog の投稿を表示しています。 すべての投稿を表示

2011/07/03

PAIProlog に atom-characters/2, string-atom/2, string-list/2 を実装

atom-characters/2, string-atom/2, string-list/2 を実装した。

https://github.com/quek/paiprolog

PAIPROLOG> (prolog-first (?x)
(atom-characters ?x (#\H #\E #\L #\L #\O)))
HELLO
PAIPROLOG> (prolog-first (?x)
(atom-characters ?x (#\H #\E #\L #\l #\O)))
|HELlO|
PAIPROLOG> (prolog-first (?x)
(atom-characters hello ?x))
(#\H #\E #\L #\L #\O)
PAIPROLOG> (prolog-first (?x)
(string-atom "hello" ?x))
|hello|
PAIPROLOG> (prolog-first (?x)
(string-atom ?x hello))
"HELLO"
PAIPROLOG> (prolog-first (?x)
(string-atom ?x |hello|))
"hello"
PAIPROLOG> (prolog-first (?x)
(string-list "hello" ?x))
(#\h #\e #\l #\l #\o)
PAIPROLOG> (prolog-first (?x)
(string-list ?x (#\h #\e #\L #\l #\o)))
"heLlo"

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))))