Previous: Interfacing nondeterministic code with the real world, Up: Determinism [Contents]
In addition to the determinism annotations described earlier,
there are “committed choice” versions of multi
and nondet
,
called cc_multi
and cc_nondet
.
These can be used instead of multi
or nondet
if all calls to that mode of the predicate (or function)
occur in a context in which only one solution is needed.
Such single-solution contexts are determined as follows.
cc_multi
or cc_nondet
is in a single-solution context.
For example, the program entry point ‘main/2’
may be declared cc_multi
,
and in that case the clauses for main
are in a single-solution context.
The compiler will check that all calls to a committed-choice mode of a predicate (or function) do indeed occur in a single-solution context.
You can declare two different modes of a predicate (or function)
which differ only in “cc-ness”
(i.e. one being multi
and the other cc_multi
,
or one being nondet
and the other cc_nondet
).
In that case,
the compiler will select the appropriate one for each call
depending on whether the call comes from a single-solution context or not.
Calls from single-solution contexts will call the committed choice version,
while calls which are not from single-solution contexts
will call the backtracking version.
There are several reasons to use committed choice determinism annotations.
One reason is for efficiency:
committed choice annotations allow the compiler
to generate much more efficient code.
Another reason is for doing I/O,
which is allowed only in det
or cc_multi
predicates,
not in multi
predicates.
Another is for dealing with types that use non-canonical representations
(see User-defined equality and comparison).
And there are a variety of other applications.
Previous: Interfacing nondeterministic code with the real world, Up: Determinism [Contents]