Querying¶
Every query takes an explicit rulebase and a goal, and returns solutions. There is no global database — see Rule DSL for building rulebases and Architecture for why state is explicit.
(query-prolog rb '(ancestor tom ?who)) ; all solutions
(query-prolog rb '(ancestor tom ?who) :limit 2) ; bounded search
(query-prolog-first rb '(ancestor ?x bob)) ; first solution or NIL
(prolog-succeeds-p rb '(ancestor tom eve)) ; boolean, stops at first proof
;; streaming: the function is called as each solution is proven
(map-prolog-solutions
(lambda (solution) (format t "~&=> ~S~%" solution))
rb '(ancestor tom ?who))
with-prolog-query binds variables from the first solution; prolog-match
dispatches like cond over queries (both are covered in the
Rule DSL).
Entry points¶
| Function | Returns |
|---|---|
map-prolog-solutions |
Nothing useful; calls your function per solution. |
query-prolog |
A list of solution alists. |
query-prolog-first |
The first solution alist, or nil. |
prolog-succeeds-p |
A boolean. |
solution-binding |
One variable's value from a solution alist. |
map-prolog-solutions— the primitive. Calls a function once per solution as it is proven (streaming CPS). Keywords::max-depth,:environment,:project,:limit.query-prolog— collects solutions into a list. Same keywords. This ismap-prolog-solutionswith an accumulating callback.query-prolog-first— first solution ornil(searches with:limit 1).prolog-succeeds-p— boolean; stops at the first proof. Supports:max-depth.solution-binding— looks one variable up in a solution alist.
Keyword options¶
| Keyword | Meaning |
|---|---|
:limit |
nil or a positive integer; caps the number of solutions. |
:max-depth |
nil (unbounded) or a non-negative integer; bounds user-rule resolution. |
:project |
nil returns raw proof environments instead of binding alists. |
:environment |
A starting binding environment for the search. |
map-prolog-solutions, query-prolog, query-prolog-first, and (for
:max-depth) prolog-succeeds-p accept these. See the
API Reference for the exact per-function support.
Result conventions¶
A solution is an alist of query-variable bindings. The empty-vs-(nil)
distinction trips up newcomers, so it is worth stating precisely:
| Outcome | Result |
|---|---|
| No proof (failure) | () |
| One ground proof, no variables | (nil) |
| Proofs that bind variables | (((?x . a)) ((?x . b)) ...) |
:project nilreturns raw proof environments instead of projected alists.- Ground success is the empty alist
nil, so "one ground proof" is the one-element list(nil), while failure is the empty list().
See it in Troubleshooting
If (nil) or a nil from query-prolog-first surprises you, the
Troubleshooting page walks through each case.
Depth bounds¶
:max-depth optionally bounds user-rule resolution (the default is NIL,
meaning unbounded). Depth decreases when proof enters a user rule, not for every
builtin or unification step.
nil— unbounded search (the default).0— disables rule expansion entirely; facts and builtins still match.n— permits up tonlevels of user-rule expansion.
Exhaustion signals prolog-depth-limit-exceeded rather than masquerading as
logical failure, so an incomplete search is never reported as "no solutions".
See Semantics and Conditions and Errors.
Validation¶
The option list is validated up front, so mistakes fail loudly instead of being silently ignored:
:limitmust benilor a positive integer; any other value signals atype-error.- An odd-length option list or an unrecognized keyword signals a
program-error. - An invalid
:max-depth(notnilor a non-negative integer) signalsinvalid-max-depth-error.
Next steps¶
- Rule DSL — build and extend the rulebases you query.
- Builtin Goals — the goals you can put in a query.
- Cookbook — streaming, counting, and bounded-search recipes.