By default foreign predicates are deterministic. Using the PL_FA_NONDETERMINISTIC attribute (see PL_register_foreign()) it is possible to register a predicate as a non-deterministic predicate. Writing non-deterministic foreign predicates is slightly more complicated as the foreign function needs context information for generating the next solution. Note that the same foreign function should be prepared to be simultaneously active in more than one goal. Suppose the natural_number_below_n/2 is a non-deterministic foreign predicate, backtracking over all natural numbers lower than the first argument. Now consider the following predicate:
quotient_below_n(Q, N) :- natural_number_below_n(N, N1), natural_number_below_n(N, N2), Q =:= N1 / N2, !.
In this predicate the function natural_number_below_n/2 simultaneously generates solutions for both its invocations.
Non-deterministic foreign functions should be prepared to handle three different calls from Prolog:
Both the context information and the type of call is provided by an argument of type foreign_t appended to the argument list for deterministic foreign functions. The macro PL_foreign_control() extracts the type of call from the control argument. The foreign function can pass a context handle using the PL_retry() macro and extract the handle from the extra argument using the PL_foreign_context() macro.
Note: If a non-deterministic foreign function returns using PL_succeed or PL_fail, Prolog assumes the foreign function has cleaned its environment. No call with control argument PL_CUTTED will follow.
The code of figure shows a skeleton for a
non-deterministic foreign predicate definition.
Figure: Skeleton for non-deterministic foreign functions