These predicates are simply derived from the control constructs and provide additional facilities for affecting the control flow during execution.
\+/1
(not provable)'\\+'(Term)
is true iff call(Term)
is false.
Templates and modes for the predicate are as follows:
'\\+'(@callable_term)
Note that \+
is a predefined operator.
Let's start with some simple tests verifying success or failure of single goals.
jTrolog.engine.SimpleGoalFixture | ||
goal | success() | exception() |
'\\+'(true). | false | no exception |
\+(!). | false | no exception |
'\\+'((!, fail)). | true | no exception |
'\\+'(4 = 5). | true | no exception |
\+(3). | false | type_error(callable, 3) |
'\\+'(X). | false | instantiation_error |
\+(X = f(X)). |
Now we run some tests also 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 | jTrolog.engine.EngineFixture |
Then, ask the engine to solve a query, and check variable bindings.
fit.ActionFixture | ||
enter | query | (X=1; X=2), \+((!, fail)). |
check | hasSolution | true |
enter | variable | X |
check | binding | 1 |
check | hasAnotherSolution | true |
enter | variable | X |
check | binding | 2 |
The remaining tests cover the cases when an error or exception is thrown by the engine while solving a query.
jTrolog.engine.PrologActionFixture | ||
enter | query | \+(3). |
check | hasSolution | false |
check | exception | type_error(callable, 3) |
enter | query | '\\+'(X). |
check | hasSolution | false |
check | exception | instantiation_error |
once/1
once(Term)
is true iff call(Term)
is true.
once(Term)
behaves as call(Goal)
but it is not re-executable.
Templates and modes for the predicate are as follows:
once(+callable_term)
Let's start with some simple tests verifying success or failure of single goals.
jTrolog.engine.SimpleGoalFixture | ||
goal | success() | exception() |
once(!). | true | no exception |
once(repeat). | true | no exception |
once(fail). | false | no exception |
once(X = f(X)). |
Now we run some tests also 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 | jTrolog.engine.EngineFixture |
Then, ask the engine to solve a query, and check variable bindings.
fit.ActionFixture | ||
enter | query | once(!), (X=1; X=2). |
check | hasSolution | true |
enter | variable | X |
check | binding | 1 |
check | hasAnotherSolution | true |
enter | variable | X |
check | binding | 2 |
Note that there are no tests covering the cases when an error or exception is thrown by the engine while solving a query using this predicate.
repeat/0
repeat
is true.
Templates and modes for the predicate are as follows:
repeat
Note that repeat
is re-executable.
Let's start with some simple tests verifying success or failure of single goals.
jTrolog.engine.SimpleGoalFixture | ||
goal | success() | exception() |
repeat, !, fail. | false | no exception |
cut/0
cut
is true.
Cut or !/0 is a sneaky devil. Be aware of how it handles different points on the stack. When cut is called, it is a leaf node on the solution tree. Cut goes 'upwards' in the resolution tree. When it reaches the next node, it removes all alternatives in all the branches of this node (in practice previous alternatives on the left branch). If cut, encounters a 'transparent' node, it will continue upwards. If cut encounters a non-transparent node, it will cut on this node, but then stop. A transparent node is either: a) a comma or b) a semicolon that does not have '->'/2 as its left node (Prolog 'if').
cut !/0
Simple and more complex tests verifying success or failure of single goals and that the resolution tree has been traversed correctly.
jTrolog.engine.PrologActionFixture | ||
enter | theory |
twice(!) :- write('C'). twice(true) :- write('Moss'). goal((twice(_), !)). goal(write('Three')). |
enter | query | !. |
check | hasSolutionWithOutput | true |
enter | query | (!, fail ; true). |
check | hasSolutionWithOutput | fail |
enter | query | (call(!), fail ; true). |
check | hasSolutionWithOutput | true |
enter | query | twice(_), !, write('Forwards'), fail. |
check | hasSolutionWithOutput | false |
check | output | CForwards |
enter | query | (! ; write('No')), write('Cut disjunction'), fail. |
check | hasSolutionWithOutput | false |
check | output | Cut disjunction |
enter | query | twice(_), (write('No') ; !), write('Cut'), fail. |
check | hasSolutionWithOutput | false |
check | output | CNoCutCut |
enter | query | twice(_), (!, fail; write('No')). |
check | hasSolutionWithOutput | false |
check | output | C |
enter | query | twice(X), call(X), write('Forwards'), fail. |
check | hasSolutionWithOutput | false |
check | output | CForwardsMossForwards |
enter | query | goal(X), call(X), write('Forwards'), fail. |
check | hasSolutionWithOutput | false |
check | output | CForwardsThreeForwards |
enter | query | twice(_), \+(\+(!)), write('Forwards'), fail. |
check | hasSolutionWithOutput | false |
check | output | CForwardsMossForwards |
enter | query | twice(_), once(!), write('Forwards'), fail. |
check | hasSolutionWithOutput | false |
check | output | CForwardsMossForwards |
enter | query | twice(_), call(!), write('Forwards'), fail. |
check | hasSolutionWithOutput | false |
check | output | CForwardsMossForwards |
The results of the tests for Logic and control are as follows:
fit.Summary |