A common issue with Prolog programs of a procedural nature is to guarantee deterministic behaviour and debug possible problems with determinism. SWI-Prolog provides several mechanisms to make writing, debugging and maintaining deterministic code easier. One of them is Single Sided Unification using =>/2 rules as described in section 5.6. This section deals with annotating your program.
WARNING: The primitives in this section are experimental. The naming and exact semantics may change. If you are interested in this, please follow and contribute to discussion on the Discourse forum.
det
, deterministic.
As a result, both failure and success with a choicepoint is considered
an error. The behaviour if the declaration is violated is controlled
with the Prolog flag determinism_error.
The default is to raise an exception (error
). Consider the
following program:
:- det(p/1). p(1). p(2).
Now, a call ?- p(1).
behaves normally. However:
?- p(X). ERROR: Deterministic procedure p/1 succeeded with a choicepoint ERROR: In: ERROR: [10] p(1) ?- p(a). ERROR: Deterministic procedure p/1 failed ERROR: In: ERROR: [10] p(a)
determinism_error
exception.
Note that if $/1
is used for the last call, last call optimization is not effective. This
behaviour ensures consistent errors or warnings. Last call optimization
with determinism checking can be realised using ..., $, Last.
,
i.e. by executing
$/0 before the
last call rather than wrapping the last call in $/1.
A deterministic predicate may call normal predicates. No error is triggered as long as the deterministic predicate either ignores a possible failure, e.g., using \+/1 and prunes possible choice points created by called predicates. If the last predicate is a normal predicate the requirement to succeed deterministically is transferred to the new goal. As last-call optimization causes the information which predicate initially claimed to be deterministic to be lost, the error is associated with the called predicate. Debug mode (see debug/0 or the Prolog flag debug) may be used to avoid last call optimization and find the call stack that causes the issue.