Coroutining allows us to delay the execution of Prolog goals until their truth can be safely decided.
Among the most important coroutining predicates is dif/2, which expresses disequality of terms in a sound way. The actual test is delayed until the terms are sufficiently different, or have become identical. For example:
?- dif(X, Y), X = a, Y = b. X = a, Y = b. ?- dif(X, Y), X = a, Y = a. false.
There are also lower-level coroutining predicates that are intended as building blocks for higher-level constraints. For example, we can use freeze/2 to define a variable that can only be assigned an atom:
?- freeze(X, atom(X)), X = a. X = a.
In this case, calling atom/1 earlier causes the whole query to fail:
?- atom(X), X = a. false.
If available, domain-specific constraints should be used in such cases. For example, to state that a variable can only assume even integers, use the CLP(FD) constraint #=/2:
?- X mod 2 #= 0. X mod 2#=0.
Importantly, domain-specific constraints can apply stronger propagation by exploiting logical properties of their respective domains. For example:
?- X mod 2 #= 0, X in 1..3. X = 2.
Remaining constraints, such as X mod 2#=0
in the example
above, are called residual goals.
They are said to
flounder, because their truth is
not yet decided. Declaratively, the query is only true if all residual
goals are satisfiable. Use call_residue_vars/2
to collect all variables that are involved in constraints.
This predicate behaves as if defined by
dif(X, Y) :- when(?=(X,Y), X \== Y)
. See also ?=/2.
The implementation can deal with cyclic terms.
The dif/2
predicate is realised using attributed variables associated with the
module dif
. It is an autoloaded predicate that is defined
in the library library(dif)
.
freeze
. See also frozen/2.true
.
Note that
frozen/2
reports all delayed goals, not only those delayed due to
freeze/2.
The goals are extracted using copy_term/3.194Versions
prior to 8.3.7 only report goals delayed using freeze/2
on a plain variable. The new behaviour is compatible with SICStus.
See also
term_attvars/2
and call_residue_vars/2.?=(X, Y)
, nonvar(X)
, ground(X)
,
,
(Cond1, Cond2)
or ;
(Cond1,
Cond2)
. See also freeze/2
and dif/2.
The implementation can deal with cyclic terms in X and Y.
The when/2
predicate is realised using attributed variables associated with the
module when
. It is defined in the autoload library
library(when)
.