Control constructs

These predicates have the effect of controlling the execution flow of a Prolog demonstration.

1. call/1

call(G) is true iff G represents a goal which is true. When G contains ! as a subgoal, the effect of ! shall not extend outside G.

Executing a call has the effect that (a) if G should fail, then the call will fail, and (b) G can be re-executed, and (c) any cut inside G is local to G.

Templates and modes for the predicate are as follows:

call(+callable_term)

1.1 Example tests

Let's start with some simple tests verifying success of failure of single goals.

alice.tuprolog.SimpleGoalFixture
goalsuccess()
call(!). true
call(fail). false
call((fail, X)). false
call((fail, call(1))). false

Let's run some tests verifying the unification for some of the variables in goals.

First of all, let's start an appropriate fixture containing an engine.

fit.ActionFixture
start alice.tuprolog.EngineFixture

Let's now use a real theory to exercise the predicate on.

fit.ActionFixture
enter theory b(X) :- Y = (write(X), X), call(Y).
a(1).
a(2).
enter query b(_).
check hasSolutionWithOutput false This should really throw an instantiation_error
check output
enter query b(3).
check hasSolutionWithOutput false This should really throw a type_error(callable, 3)
check output 3
enter query Z = !, call((Z = !, a(X), Z)).
check hasSolution true
enter variable X
check binding 1
enter variable Z
check binding !
check hasAnotherSolution false
enter query call((Z = !, a(X), Z)).
check hasSolution true
enter variable X
check binding 1
enter variable Z
check binding !
check hasAnotherSolution true
enter variable X
check binding 2
enter variable Z
check binding !
check hasAnotherSolution false

The remaining tests cover the cases when an error or exception is thrown by the engine while solving a query.

alice.tuprolog.PrologActionFixture
enter query call((write(3), X)).
check hasSolutionWithOutput false
check output 3
check exception instantiation_error
enter query call((write(3), call(1))).
check hasSolutionWithOutput false
check output 3
check exception type_error(callable, 1)
enter query call(X).
check hasSolution false
check exception instantiation_error
enter query call(1).
check hasSolution false
check exception type_error(callable, 1)
enter query call((fail, 1)).
check hasSolution false
check exception type_error(callable, (fail, 1))
enter query call((write(3), 1)).
check hasSolution false
check exception type_error(callable, (write(3), 1))
enter query call((1 ; true)).
check hasSolution false
check exception type_error(callable, (1 ; true))

2. (;)/2 (disjunction)

';'(Either, Or) is true iff Either is true or Or is true.

Note that (;)/2 is re-executable.

Executing a disjunction has the effect that (a) if Either shoud fail, then Or will be executed on backtracking, and (b) disjunction is transparent to cut.

Templates and modes for the predicate are as follows:

';'(goal, goal)

Note that ';' is an predefined infix operator.

1.1 Example tests

Let's start with some simple tests verifying success of failure of single goals.

alice.tuprolog.SimpleGoalFixture
goal success()
';'(true, fail). true
';'((!, fail), true). false
';'(!, call(3)). true

Now let's run some tests verifying the unification for some of the variables in goals.

First of all, let's start an appropriate fixture containing an engine.

fit.ActionFixture
start alice.tuprolog.EngineFixture

Then, ask the engine to solve a query, and check variable bindings.

fit.ActionFixture
enter query ';'((X = 1, !), X = 2).
check hasSolution true
enter variable X
check binding 1
enter query ','(';'(X = 1, X = 2), ';'(true, !)).
check hasSolution true
enter variable X
check binding 1
check hasAnotherSolution true
enter variable X
check binding 1
check hasAnotherSolution false

No error or exception is thrown by the engine while solving a query with (;)/2.

3. (->)/2 (if-then)

'->'(If, Then) is true iff (1) If is true, and (2) Then is true for the first solution of If.

Note that (->)/2 is re-executable.

Executing an if-then has the effect that (a) if If shoud fail, then if-then will fail, and (b) if If should succeed, then Then will be executed

, and (c) if If should succeed and Then later fails, the If will not be re-executed because of the cut which has been executed, and (d) the If in an if-then is not transparent to cut, and (e) a cut in Then is transparent to if-then.

Templates and modes for the predicate are as follows:

'->'(goal, goal)

Note that '->' is an predefined infix operator.

1.1 Example tests

Let's start with some simple tests verifying success of failure of single goals.

alice.tuprolog.SimpleGoalFixture
goal success()
'->'(true, true). true
'->'(true, fail). false
'->'(fail, true). false

Now let's run some tests verifying the unification for some of the variables in goals.

First of all, let's start an appropriate fixture containing an engine.

fit.ActionFixture
start alice.tuprolog.EngineFixture

Then, ask the engine to solve a query, and check variable bindings.

fit.ActionFixture
enter query '->'(true, X = 1).
check hasSolution true
enter variable X
check binding 1
check hasAnotherSolution false
enter query '->'(';'(X = 1, X = 2), true).
check hasSolution true
enter variable X
check binding 1
check hasAnotherSolution false
enter query '->'(true, ';'(X = 1, X = 2)).
check hasSolution true
enter variable X
check binding 1
check hasAnotherSolution true
enter variable X
check binding 2
check hasAnotherSolution false

No error or exception is thrown by the engine while solving a query with (->)/2.

4. (;)/2 (if-then-else)

(;)/2 serves two different functions depending on whether or not the first argument is a compound term with functor (->)/2.

';'('->'(If, Then), Else) is true iff (1a) If is true, and (1b) Then is true for the first solution of If, or (2) If is false and Else is true.

Note that (;)/2 is re-executable. The cut prevents and if-then-else from being re-executed a second time.

Executing an if-then-else has the effect that (a) if If shoud fail, then if-then-else will be re-executed, and (b) if If should succeed, then Then will be executed

, and (c) if If should succeed and Then later fails, the if-the-else will not be re-executed because of the cut which has been executed, and (d) the If in an if-then-else is not transparent to cut, and (e) a cut in Then is transparent to Then.

Re-executing an if-then-else has the effect that (a) the Else will be executed, and (b) if Else later fails, the if-then-else will not be re-executed again because of the cut which has been executed, and (c) a cut in Else is transparent to Else.

Templates and modes for the predicate are as follows:

';'('->'(goal, goal), goal)

Note that ';' '->' are predefined infix operators so that (If -> Then ; Else) is parsed as ';'('->'(If, Then), Else).

1.1 Example tests

Let's start with some simple tests verifying success of failure of single goals.

alice.tuprolog.SimpleGoalFixture
goal success()
';'('->'(true, true), fail). true
';'('->'(true, fail), fail). false
';'('->'(fail, true), true). true
';'('->'(fail, true), fail). false
';'('->'((!, fail), true), true). true

Now let's run some tests verifying the unification for some of the variables in goals.

First of all, let's start an appropriate fixture containing an engine.

fit.ActionFixture
start alice.tuprolog.EngineFixture

Then, ask the engine to solve a query, and check variable bindings.

fit.ActionFixture
enter query ';'('->'(true, X = 1), X = 2).
check hasSolution true
enter variable X
check binding 1
enter query ';'('->'(fail, X = 1), X = 2).
check hasSolution true
enter variable X
check binding 2
enter query ';'('->'(true, ';'(X = 1, X = 2)), true).
check hasSolution true
enter variable X
check binding 1
check hasAnotherSolution true
enter variable X
check binding 2
enter query ';'('->'(';'(X = 1, X = 2), true), true).
check hasSolution true
enter variable X
check binding 1

No error or exception is thrown by the engine while solving a query with (;)/2.

Run the tests!


The results of the tests for All solutions are as follows:

fit.Summary