## 4.8 Control Predicates

The predicates of this section implement control structures. Normally the constructs in this section, except for repeat/0, are translated by the compiler. Please note that complex goals passed as arguments to meta-predicates such as findall/3 below cause the goal to be compiled to a temporary location before execution. It is faster to define a sub-predicate (i.e. one_character_atoms/1 in the example below) and make a call to this simple predicate.

    one_character_atoms(As) :-
            findall(A, (current_atom(A), atom_length(A, 1)), As).

[ISO]fail
  Always fail. The predicate fail/0 is translated into a single virtual machine instruction.
[ISO]false
  Same as fail, but the name has a more declarative connotation.
[ISO]true
  Always succeed. The predicate true/0 is translated into a single virtual machine instruction.
[ISO]repeat
  Always succeed, provide an infinite number of choice points.
[ISO]!
  Cut. Discard all choice points created since entering the predicate in which the cut appears. In other words, commit to the clause in which the cut appears and discard choice points that have been created by goals to the left of the cut in the current clause. Meta calling is opaque to the cut. This implies that cuts that appear in a term that is subject to meta-calling (call/1) only affect choice points created by the meta-called term. The following control structures are transparent to the cut: ;/2, ->/2 and *->/2. Cuts appearing in the condition part of ->/2 and *->/2 are opaque to the cut. The table below explains the scope of the cut with examples. Prunes here means ``prunes X choice point created by X''.

  `t0 :- (a, !, b).` | % prunes a/0 and t0/0
  `t1 :- (a, !, fail ; b).` | % prunes a/0 and t1/0
  `t2 :- (a -> b, ! ; c).` | % prunes b/0 and t2/0
  `t3 :- call((a, !, fail ; b)).` | % prunes a/0
  `t4 :- `\+`(a, !, fail).` | % prunes a/0

[ISO]:Goal1 , :Goal2
  Conjunction. True if both `Goal1' and `Goal2' can be proved. It is defined as follows (this definition does not lead to a loop as the second comma is handled by the compiler):

      Goal1, Goal2 :- Goal1, Goal2.

[ISO]:Goal1 ; :Goal2
  The `or' predicate is defined as:

      Goal1 ; _Goal2 :- Goal1.
      _Goal1 ; Goal2 :- Goal2.

:Goal1 | :Goal2
  Equivalent to ;/2. Retained for compatibility only. New code should use ;/2.
[ISO]:Condition -> :Action
  If-then and If-Then-Else. The ->/2 construct commits to the choices made at its left-hand side, destroying choice points created inside the clause (by ;/2), or by goals called by this clause. Unlike !/0, the choice point of the predicate as a whole (due to multiple clauses) is not destroyed. The combination ;/2 and ->/2 acts as if defined as:

      If -> Then; _Else :- If, !, Then.
      If -> _Then; Else :- !, Else.
      If -> Then :- If, !, Then.

  Please note that (If `->` Then) acts as (If `->` Then ; fail), making the construct fail if the condition fails. This unusual semantics is part of the ISO and all de-facto Prolog standards.

:Condition *-> :Action ; :Else
  This construct implements the so-called `soft-cut'. The control is defined as follows: If Condition succeeds at least once, the semantics is the same as (Condition, Action). If Condition does not succeed, the semantics is that of (`\+` Condition, Else). In other words, if Condition succeeds at least once, simply behave as the conjunction of Condition and Action, otherwise execute Else.

  The construct A `*->` B, i.e. without an Else branch, is translated as the normal conjunction A, B.bugThe decompiler implemented by clause/2 returns this construct as a normal conjunction too.

[ISO]\+ :Goal
  True if `Goal' cannot be proven (mnemonic: ``+`` refers to provable and the backslash (``\``) is normally used to indicate negation in Prolog).