Node:Finding Multiple Solutions of a Call, Next:Calling Prolog Asynchronously, Previous:Finding One Solution of a Call, Up:Calling Prolog
If you are interested in more than one solution a more complicated scheme is used. You find the predicate definition as abov, but you don't call the predicate directly.
SP_open_query()
SP_next_solution()
to find a solution. Call this predicate
again to find more solutions if there are any.
SP_close_query()
or SP_cut_query()
The function SP_open_query()
will return an identifier of type
SP_qid
that you use in successive calls, or 0
, if given
an invalid predicate reference. Note that if a new query is opened
while another is already open, the new query must be terminated before
exploring the solutions of the old one. That is, queries must be
strictly nested:
SP_qid SP_open_query(SP_pred_ref predicate, SP_term_ref arg1, ...)
The function SP_next_solution()
will cause the Prolog engine to
backtrack over any current solution of an open query and look for a new
one. The given argument must be the innermost query that is still open,
i.e. it must not have been terminated explicitly by
SP_close_query()
or SP_cut_query()
or implicitly by an
unsuccessful call to SP_next_solution()
. Returns
SP_SUCCESS
for success, SP_FAILURE
for failure,
SP_ERROR
if an error condition occurred. Only when the return
value is SP_SUCCESS
are the values in the query arguments valid,
and will remain so until backtracking into this query or an enclosing
one:
int SP_next_solution(SP_qid query)
A query must be terminated in either of two ways.
The function
SP_cut_query()
will discard the choices created since the
corresponding SP_open_query()
, like the goal !
.
The current solution is retained in the arguments
until backtracking into any enclosing query.
The given argument does not have to be the innermost open query; any
open queries in its scope will also be cut. Returns SP_SUCCESS
for success and SP_ERROR
for invalid usage:
int SP_cut_query(SP_qid query)
Alternatively, the function SP_close_query()
will discard the
choices created since the corresponding SP_open_query()
, and then
backtrack into the query, throwing away any current solution, like the
goal !, fail
.
The given argument does not have to be the innermost open query; any
open queries in its scope will also be closed. Returns
SP_SUCCESS
for success and SP_ERROR
for invalid usage:
int SP_close_query(SP_qid query)
A simple way to call arbitrary prolog code is to use
SP_read_from_string
(see Creating Prolog Terms) to create an
argument to call/1
. It is a good idea to always explicitly
specify the module context when using call/1
or other meta
predicates from C.
This example calls a compound goal (without error checking).
SP_pred_ref call_pred = SP_predicate("call", 1, "prolog"); SP_term_ref x = SP_new_term_ref(); SP_term_ref goal = SP_new_term_ref(); SP_term_ref vals[] = {x, 0 /* zero termination */}; long len; SP_put_variable(x); /* The X=_ is a trick to ensure that X is the first variable in the depth-first order and thus corresponds to vals[0] (x). There are no entries in vals for _,L1,L2. */ SP_read_from_string(goal, "user:(X=_, length([0,1,2],L1), length([3,4],L2), X is L1+L2).", vals); SP_query(call_pred, goal); SP_get_integer(x, &len); /* here len is 5 */