There are several entry points provided for calling Prolog from Lisp. The main interface function is called logic
and has numerous options. The basic form is:
(logic <goal> :return-type <return-type> :all <all-type> :bag-exp <bag-exp>)
The keyword arguments are interpreted as follows:
:return-type
describes what to do with a solution when one is found. Possible values of :return-type
are:
:display |
Display variable bindings and prompt user (the option used by the read-query-print loop). |
:fill |
Instantiate the goal expression and return it. |
:bag |
Instantiate <bag-exp> and return it. |
:alist | Return an alist of variables and bindings.
The default is |
:all
tells what to do with multiple solutions. Possible values of :all
are:
nil |
Return the first solution. |
:values |
Return multiple solutions as multiple values. |
:list |
Return a list of the solutions. |
:bag-exp
is an expression that should be instantiated with the bindings from a solution. This is only meaningful if :return-type
is :bag
.
(logic '(color ?x) :return-type :display)
writes:
?X = RED<wait for input>
(logic '(color ?x) :return-type :fill)
returns:
(COLOR RED) T
(logic '(color ?x) :return-type :alist)
returns:
((?X . RED)) T
(logic '(color ?x) :all :list)
returns:
((COLOR RED) (COLOR BLUE) (COLOR GREEN)) T
(logic '(color ?x) :return-type :bag :bag-exp '(?x is a color) :all :values)
returns:
(RED IS A COLOR) (BLUE IS A COLOR) (GREEN IS A COLOR)
There are three additional ways to call logic
, which are described in this section.
Three simple interface functions call logic
. They are any, findall, and findallset. Each takes two arguments: a result expression to instantiate and a goal expression. any returns the first solution found. findall returns all solutions. findallset
returns all solutions deleting duplicates.
Assuming the definitions for fact
and color
from the previous examples.
|(any '(?x is the factorial of 5) '(fact 5 ?x))
returns:
| |(120 IS THE FACTORIAL OF 5) |
|(findall '(?x is a color) '(color ?x))
returns:
| |((RED IS A COLOR) (BLUE IS A COLOR) (GREEN IS A COLOR)) |
|(findall '?y '(or (= ?y 5) (= ?y 5)))
returns:
| |(5 5) | |(findallset '?y '(or (= ?y 5) (= ?y 5)))
returns:
| |(5)
findall and findallset
will hang if a goal expression generates an infinite solution set.
More powerful all solution predicates (bagof
and setof
) are available from within Common Prolog.
A different interface is available for predicates which will be called often from Lisp. The macro deflogfun
may be used to generate normal Lisp functions that run with precompiled goals.
(deflogfun break-up (y) (append ?a ?b y) (?a ?b))
then:
(break-up '(foo bar baz))
returns:
(NIL (FOO BAR BAZ)) T
(break-up '(foo bar baz) :all :values)
returns:
(NIL (FOO BAR BAZ)) ((FOO) (BAR BAZ)) ((FOO BAR) (BAZ)) ((FOO BAR BAZ) NIL)
(break-up '(foo bar baz) :all :list)
returns:
((NIL (FOO BAR BAZ)) ((FOO) (BAR BAZ)) ((FOO BAR) (BAZ)) ((FOO BAR BAZ) NIL)) T
The generated function works like the Lisp functions any and findall, returning solutions to a prolog expression.
The form:
(deflogfun name args sample-expr return-expr)
defines a Lisp function called name, whose lambda list is the list args. The function will also take a keyword argument :all
. If the function is called with :all nil
(the default), then it returns the first solution, like any. If the function is called with :all t
, then it returns a list of all the solutions, like findall. If the function is called with :all :values
, then it returns multiple values, with one value per solution.
The sample-expr is like the second argument to any, that is, it is the prolog query expression. The return-expr is like the first argument to clog:any, that is, it defines how the result will be formed from the results of the query. If any of the symbols mention in args appears in sample-expr or return-expr, then its value is substituted. All other symbols in sample-expr and return-expr remain unchanged.
A final interface mechanism is with-prolog
, which allows you to embed prolog into an arbitrary lisp function. Lisp variables are referenced in Prolog using "?.<name>
".
(defun palindromep (x) (with-prolog (append ?a (?b . ?c) ?.x) ; note "?.x" reference (or (reverse ?a ?c) (reverse ?a (?b . ?c))))) (palindromep '(yes no maybe))
returns:
NIL (palindromep '(yes no maybe no yes))
returns:
T
The body of a with-prolog
returns t
if it succeeds and a non-local exit is not executed. It returns nil
on failure.
KnowledgeWorks and Prolog User Guide (Macintosh version) - 01 Dec 2021 19:35:39