Examples¶
The repository ships three runnable programs under examples/. They are loaded
as the cl-prolog/examples ASDF system, which loads the library first and then
executes all three files:
sbcl --non-interactive \
--eval '(require :asdf)' \
--eval '(asdf:load-asd (truename "cl-prolog.asd"))' \
--eval '(asdf:load-system :cl-prolog/examples)'
Not standalone scripts
The example files are not standalone scripts. Invoking one directly
with sbcl --script does not load the cl-prolog package. Load them
through the cl-prolog/examples system, which is also exercised by the
checks.examples Nix check (Development).
quick-start.lisp — the smallest useful program¶
(in-package #:cl-prolog)
(define-rulebase *family*
((parent tom bob))
((parent bob alice))
((ancestor ?x ?y) (parent ?x ?y))
((ancestor ?x ?y) (parent ?x ?z) (ancestor ?z ?y)))
(format t "~&quick-start ancestor(tom, ?who) => ~S~%"
(query-prolog *family* '(ancestor tom ?who)))
Two parent/2 facts and a recursive ancestor/2 definition. query-prolog
returns every solution as a list of binding alists.
family-tree.lisp — three ways to query¶
(in-package #:cl-prolog)
(define-rulebase *family*
((parent tom bob))
((parent bob alice))
((parent alice eve))
((ancestor ?x ?y) (parent ?x ?y))
((ancestor ?x ?y) (parent ?x ?z) (ancestor ?z ?y)))
(format t "~&ancestor(tom, ?who) => ~S~%"
(query-prolog *family* '(ancestor tom ?who)))
(format t "first ancestor(tom, ?who) => ~S~%"
(query-prolog-first *family* '(ancestor tom ?who)))
(format t "parent(tom, bob) succeeds => ~S~%"
(prolog-succeeds-p *family* '(parent tom bob)))
The same rulebase, queried three ways:
query-prolog— all solutions as a list.query-prolog-first— the first solution, ornil.prolog-succeeds-p— a boolean yes/no.
This is the program walked through step by step in Your First Program.
relational-lists.lisp — list relations without any clauses¶
(in-package #:cl-prolog)
(let ((rulebase (make-rulebase)))
(format t "~&append(?l ?r (a b c)) => ~S~%"
(query-prolog rulebase '(append ?l ?r (a b c))))
(format t "reverse(?xs (c b a)) => ~S~%"
(query-prolog rulebase '(reverse ?xs (c b a))))
(format t "length(?xs 3) => ~S~%"
(query-prolog-first rulebase '(length ?xs 3)))
(format t "member(?x (a b c)) => ~S~%"
(query-prolog rulebase '(member ?x (a b c)))))
make-rulebase builds an empty rulebase. The list predicates are builtins,
so they work with no user clauses at all:
append/3run "backwards" enumerates every way to split(a b c)into a prefix?land suffix?r.reverse/2binds?xsto the reverse of(c b a).length/2with an unbound list and a fixed length generates a list of three fresh variables — see the relationallength/2notes in Builtin Goals.member/2enumerates each element of(a b c)in turn.
Where to go next¶
- Cookbook — more task-oriented recipes.
- Builtin Goals — the full builtin catalogue.
- Testing — how the query test helpers assert on these shapes.