,
+Q ISO ;
+Q ISO!
ISO\+
+P ISOFails if the goal P has a solution, and succeeds otherwise. This is not real negation (“P is false”), but a kind of pseudo-negation meaning “P is not provable”. It is defined as if by
\+(P) :- P, !, fail. \+(_).
In sicstus
execution mode no cuts are allowed in
P. In iso
execution mode cuts are allowed in P
and their scope is the goal P.
Remember that with prefix operators such as this one it is necessary to be careful about spaces if the argument starts with a `('. For example:
| ?- \+ (P,Q).
is this operator applied to the conjunction of P and Q, but
| ?- \+(P,Q).
would require a predicate \+ /2
for its solution. The
prefix operator can however be written as a functor of one
argument; thus
| ?- \+((P,Q)).
is also correct.
->
+Q ;
+R ISOif P then Q else R
and defined as if by
(P -> Q; R) :- P, !, Q. (P -> Q; R) :- R.
except the scope of any cut in Q or R extends beyond
the if-then-else construct. In sicstus
execution mode no
cuts are allowed in P. In iso
execution mode
cuts are allowed in P and their scope is the goal
P.
Note that this form of if-then-else only explores the first solution to the goal P.
Note also that the `;' is not read as a disjunction operator in this case; instead, it is part of the if-then-else construction.
The precedence of `->' is less than that of `;' (see Operators), so the expression is read as
;(->(P,Q),R)
->
+Q ISO(P -> Q; fail)
if(
+P,
+Q,
+R)
if P then Q else R
but differs from P -> Q ; R
in that if(P, Q, R)
explores
all solutions to the goal P. There is a small time
penalty for this—if P is known to have only one solution of
interest, the form P -> Q ; R
should be preferred.
In sicstus
execution mode no cuts are allowed in
P. In iso
execution mode cuts are allowed in P
and their scope is the goal P.
once(
+P)
ISO(P -> true; fail)
otherwise
true
ISOotherwise/0
is discouraged, because
it is not as portable as true/0
, and because the former may
suggest a completely different semantics than the latter.
false
fail
ISOfalse/0
is discouraged, because it is
not as portable as fail/0
, and because the latter has a more
procedural flavor to it.
repeat
ISOrepeat/0
is hardly ever used except in
repeat loops. A repeat loop has the structure
Head :- ... save_state(OldState), repeat, generate(Datum), action(Datum), test(Datum), !, restore_state(OldState), ...
The purpose is to repeatedly perform some action on elements that are somehow generated, e.g. by reading them from a stream, until some test becomes true. Usually, generate, action, and test are all determinate. Repeat loops cannot contribute to the logic of the program. They are only meaningful if the action involves side-effects.
The only reason for using repeat loops instead of a more natural
tail-recursive formulation is efficiency: when the test fails
back, the Prolog engine immediately reclaims any working storage
consumed since the call to repeat/0
.
call(
:Term)
ISOincore(
:Term)
obsolescentcall(
Term)
is executed exactly as if that term
appeared textually in its place, except that any cut (!
)
occurring in Term only cuts alternatives in the execution of
Term. Use of incore/1
is not recommended.
If Term is not instantiated as described above, an exception
is raised.
call_cleanup(
:Goal,
:Cleanup)
When call_cleanup/2
with a continuation C is called or
backtracked into, first Goal is called or backtracked
into. Then there are four possibilities:
call_cleanup/2
Goal
is raised, Cleanup is executed with continuation
raise_exception(
E)
.
fail
.
raise_exception(
E)
.
In a typical use of call_cleanup/2
, Cleanup succeeds
determinately after performing some side-effect; otherwise,
unexpected behavior may result.
Note that the Prolog top-level operates as a read-execute-fail loop,
which backtracks into or cuts the query when the user
types ; or <RET> respectively. Also, the predicates
halt/0
and abort/0
are implemented in terms of
exceptions. All of these circumstances can trigger the execution of
Cleanup.