Builtin predicates - Logic and control

Predicates in this group are used to structure the flow of execution through a Plang program.

(&&)/2, (||)/2, (=>)/2, (<=>)/2, call/1, call/2, catch/3, (,)/2, (!)/0, commit/0, do, (!)/1, (\+)/1, fail/0, false/0, for, halt/0, halt/1, (->)/2, if, in/2, once/1, repeat/0, switch, throw/1, true/0, try, while


(&&)/2, (,)/2 - sequential execution of two goals.

Usage
Goal1 && Goal2
(Goal1, Goal2)
Description
Executes Goal1 and then executes Goal2 if Goal1 was successful.
The (&&)/2 form is recommended for use within boolean conditions for if, while, and similar statements. The (,)/2 form usually occurs as a result of parsing the statement sequence { Goal1 ; Goal2 }.
This predicate is equivalent to fuzzy_and/2 when reasoning about terms that involve fuzzy logic.
Examples
 nonvar(X); integer(X)
 (nonvar(X), integer(X))
 if (nonvar(X) && integer(X)) { ... }
Compatibility
The (,)/2 predicate is compatible with Standard Prolog. The (&&)/2 predicate is an alias for (,)/2.
See Also
(||)/2, (=>)/2, (<=>)/2, (!)/1, fuzzy_and/2

(||)/2 - alternative execution of two goals.

Usage
Goal1 || Goal2
Description
Executes Goal1 and succeeds if Goal1 succeeds. Otherwise executes Goal2.
If Goal1 or Goal2 involves terms that use fuzzy logic, then the fuzzy confidence value of Goal1 || Goal2 is the same as Goal1 while it succeeds, and then the same as Goal2 once Goal1 fails. Use the fuzzy_or/2 operator instead for calculating the logical fuzzy OR of Goal1 and Goal2.
Examples
 nonvar(X) || integer(X)
 if (atom(X) || integer(X)) { ... }
Compatibility
Standard Prolog has a (;)/2 predicate that is used for disjunction. That predicate has been omitted from Plang because it conflicts with ";" used as a conjunction operator in statement lists.
See Also
(&&)/2, (=>)/2, (<=>)/2, (!)/1, fuzzy_or/2, if

(=>)/2 - logical implication.

Usage
Goal1 => Goal2
Description
Executes Goal1. If it succeeds, then execute Goal2. If Goal1 fails, then Goal1 => Goal2 succeeds.
Implication differs from (->)/2 in that (->)/2 will fail if Goal1 fails, whereas (=>)/2 will succeed. The implication operator is intended for use in applications that involve propositional logic.
Essentially, Goal1 => Goal2 is the same as (Goal1 -> Goal2 || true).
Examples
 A => B
 true => true             succeeds
 true => false            fails
 false => true            succeeds
 false => false           succeeds
See Also
(&&)/2, (||)/2, (<=>)/2, (!)/1, (->)/2

(<=>)/2 - logical equivalence.

Usage
Goal1 <=> Goal2
Description
Executes Goal1 and Goal2. Succeeds if they both succeed or if they both fail. Fails if one succeeds and the other fails.
Essentially, Goal1 <=> Goal2 is the same as (Goal1 -> once(Goal2) || ! Goal2).
Examples
 A <=> B
 true <=> true            succeeds
 true <=> false           fails
 false <=> true           fails
 false <=> false          succeeds
See Also
(&&)/2, (||)/2, (=>)/2, (!)/1

call/1 - meta-execution of a goal.

Usage
call(Goal)
Description
If Goal is a callable term, then execute it as though it had been compiled normally. If Goal is not a callable term, then throw an error as described below.
The effect of a commit/0 inside Goal is limited to the goal itself and does not affect control flow outside the call/1 term.
Errors
Examples
 call(fail)           fails
 X = atom(a); call(X) calls atom(a) and then succeeds
 call(X)              instantiation_error
 call(1.5)            type_error(callable, 1.5)
 call((atom(a), 1.5)) atom(a) succeeds and then type_error(callable, 1.5)
Compatibility
The call/1 predicate is mostly compatible with Standard Prolog. The main departure is that Standard Prolog will scan the entire structure of Goal and throw a type_error if some part of it is not callable. The last example above would throw type_error(callable, (atom(a), 1.5)) and not execute atom(a) in Standard Prolog. Plang implements lazy evaluation of call/1 subgoals, so only the outermost layer of Goal is checked before execution begins.
See Also
call/2, commit/0, once/1

call/2 - meta-execution of a goal within the scope of a local database.

Usage
call(Goal, Database)
Description
If Goal is a callable term, then execute it as though it had been compiled normally. If Goal is not a callable term, then throw an error as described below.
Goal is executed within a context where Database is set as the current database. Predicates that are called by Goal will be looked up in Database before the global database. Builtin predicates implemented in C will always override the local database; for example, it isn't possible to redefine call/2 within a local database.
The effect of a commit/0 inside Goal is limited to the goal itself and does not affect control flow outside the call/2 term.
Errors
Examples
 new_database(DB);
 assertz(userdef(a, b, c), DB);
 call(userdef(A, B, C), DB);
See Also
assertz/2, call/1, commit/0, new_database/1

catch/3, try - catches an error that was thrown during execution of a goal.

Usage
catch(Goal, Pattern, Recovery)
try { Goal } catch (Pattern1) { Recovery1 } catch (Pattern2) { Recovery2 } ...
Description
Executes call(Goal) and succeeds or fails accordingly. If Goal throws an error with throw/1, and the error can be unified with Pattern, then call(Recovery) will be executed. If the error does not unify with Pattern, then the error will continue to be thrown further up the call chain.
In the case of the try statement, each PatternN is tried in turn until a match is found. The RecoveryN goal for that pattern is then executed. Note that this is not the same as catch(catch(Goal, Pattern1, Recovery1), Pattern2, Recovery2). The catch/3 form may execute Recovery2 if an error is thrown during Recovery1. The try statement form will not.
Compatibility
The catch/3 predicate is compatible with Standard Prolog. The try ... catch ... statement is the recommended equivalent in Plang because of its better support for multiple catch blocks.
See Also
throw/1, call/1, Formal syntax of try statements

commit/0, (!)/0 - commits the program to the current choice.

Usage
commit
!
Description
The commit/0 predicate always succeeds but also prunes alternative solutions at the next higher goal level. It is most often used in predicates with multiple clauses that match the arguments.
The following example implements a list membership testing predicate:
 is_member(X, [X|_]).
 is_member(X, [_|T]) { is_member(X, T); }
An issue with this predicate is that it will keep searching for further instances of X after finding the first. This may not be what was intended. We can solve this problem by committing to the solution once X is found:
 is_member(X, [X|_]) { commit; }
 is_member(X, [_|T]) { is_member(X, T); }
Another problem with the original version of the predicate is that if the tail of the list is a variable, it may loop indefinitely. We can solve this by adding another clause that commits and fails if the list is a variable:
 is_member(X, L) { var(L); commit; fail; }
 is_member(X, [X|_]) { commit; }
 is_member(X, [_|T]) { is_member(X, T); }
Examples
 commit           succeeds
 !                succeeds
Compatibility
The (!)/0 predicate is compatible with Standard Prolog. The new name commit is recommended because it is more obvious as to its function.
See Also
call/1

do - repeatedly execute a statement until a condition is false.

Usage
do { Statements } (Condition);
do [UnbindVars] { Statements } (Condition);
Description
The do loop evaluates Statements, and then evaluates Condition. If Condition is true, then the loop repeats. If Statements fails, then the loop will fail.
If UnbindVars is specified, then it contains a list of local variables that will be unbound at the beginning of each loop iteration before Statements is evaluated.
Examples
 X = 1; do { stdout::writeln(X); X ::= X + 1; } while (X <= 10);
 X = 1; do [Y] { Y is X * 2; stdout::writeln(Y); X ::= X + 1; } while (X <= 10);
See Also
for, while, Formal syntax of do statements

(!)/1, (\+)/1 - negation by failure.

Usage
! Term
\+ Term
Description
If call(Term) succeeds, then fail; otherwise succeed.
Note: (!)/1 does not take the current fuzzy confidence value into account, so it is not suitable for use in applications that involve fuzzy logic. Use the fuzzy_not/1 predicate instead.
Examples
 X = a; !(X = b)      succeeds with X = a
 X = a; !(X = a)      fails
 \+ fail              succeeds
 ! true               fails
Compatibility
The (\+)/1 predicate is compatible with Standard Prolog. The new name (!)/1 is the recommended spelling.
See Also
(&&)/2, (||)/2, (=>)/2, (<=>)/2, fuzzy_not/1

fail/0, false/0 - always fail.

Usage
fail
false
Description
The fail predicate always fails execution of the current goal.
Examples
 fail                 fails
 false                fails
 repeat; f(a); fail   executes f(a) an infinite number of times
Compatibility
The fail/0 predicate is part of Standard Prolog. The false/0 predicate exists as an alias in Plang because it is a more natural opposite to true/0.
See Also
true/0

for - loop over the members of a list.

Usage
for (Variable in List) Statement
for [UnbindVars] (Variable in List) Statement
Description
The for loop iterates over the members of List, binding Variable to each member in turn and performing Statement. The Variable must have a new name that does not occur previously in the clause.
If Statement fails for a member of List, then the loop will fail. If Statement succeeds for all members of List, then the loop will succeed.
If UnbindVars is specified, then it contains a list of local variables that will be unbound at the beginning of each loop iteration. The Variable must not appear in UnbindVars.
Errors
Examples
 for (X in List) { stdout::writeln(X); }
 for [Y] (X in List) { Y is X * 2; stdout::writeln(Y); }
See Also
do, in/2, while, Formal syntax of for statements

halt/0 - stops execution of the top-level goal.

Usage
halt
Description
Exits from execution of the top-level goal, returning control back to the system with an exit value of 0.
It is not possible to trap the halt state with catch/3.
Examples
 halt
 catch(halt, X, stdout::writeln('not reached'))
Compatibility
Standard Prolog
See Also
halt/1

halt/1 - stops execution of the top-level goal with a specific exit value.

Usage
halt(ExitValue)
Description
Exits from execution of the top-level goal, returning control back to the system with the specified integer ExitValue. The ExitValue may be clamped to a system-specific range to make it suitable for passing back to the host operating system.
It is not possible to trap the halt state with catch/3 if ExitValue is a valid integer.
Errors
Examples
 halt(3)
 catch(halt(3), X, stdout::writeln('not reached'))
 halt(X)              instantiation_error
 halt(1.0)            type_error(integer, 1.0)
Compatibility
Standard Prolog
See Also
halt/0

(->)/2, if - if-then statement.

Usage
if (Goal1) Goal2
if (Goal1) Goal2 else Goal3
(Goal1 -> Goal2 || true)
(Goal1 -> Goal2 || Goal3)
Description
Goal1 is executed, and if it succeeds then Goal2 is executed. If Goal1 fails, then Goal3 is executed. If Goal3 is omitted, then the statement succeeds if Goal1 fails.
If the goal has the form (Goal1 -> Goal2) without a Goal3 else goal, then the goal will fail if Goal1 fails. By contrast, if (Goal1) Goal2 will succeed if Goal1 fails.
Examples
 if (A) B; else C;
 (A -> B || C)
 if (A) B;
 (A -> B || true)         succeeds if A fails
 (A -> B)                 fails if A fails
Compatibility
The (->)/2 predicate is compatible with Standard Prolog. Standard prolog expresses if-then-else as (A -> B ; C) which is not supported in Plang. The if statement form is the recommended method to express conditionals in Plang.
See Also
(||)/2, (=>)/2, switch, Formal syntax of if statements

in/2 - list membership testing.

Usage
Term in List
Description
Term in List succeeds multiple times whenever Term unifies with an element of List. Fails at the end of the List, if Term does not unify with any of the elements, or the tail of List is not a list or [].
Errors
Examples
 X in [a, b, c]       succeeds 3 times for X = a/b/c, then fails
 f(X) in [a]          fails
 X in Y               instantiation_error
 X in [a|Y]           succeeds with X = a, then instantiation_error
Note: if the in/2 predicate is used within a condition for a do, if, or while statement, then it will succeed only once for the first match. This is because the statement conditions perform a commit/0 after success is detected. This is useful for detecting simple list membership only:
 if (f(a) in List) {
     ...
 }
The recommended procedural loop construct for lists is for:
 for (X in [a, b, c])
     stdout::writeln(X);
See Also
for

once/1 - executes a goal only once, ignoring subsequent solutions.

Usage
once(Goal)
Description
Executes call(Goal) and then executes a commit/0 to prune searches for further solutions. In essence, once(Goal) behaves like call(Goal, commit).
Examples
 once((X = a || Y = b))   succeeds with X = a, never performs Y = b
 once(fail)               fails
Compatibility
Standard Prolog
See Also
call/1

repeat/0 - succeeds repeatedly and indefinitely.

Usage
repeat; ...; fail
Description
Repeats the sequence of statements between repeat and fail indefinitely until a commit/0 is encountered.
Examples
 repeat; stdout::writeln("hello"); fail
                      outputs "hello" indefinitely
 repeat; !            succeeds
 repeat; !; fail      fails
 repeat; fail         loops indefinitely
 repeat; a = b        loops indefinitely due to unification failure
Compatibility
Standard Prolog
See Also
fail/0

switch - switch on a term and choose a matching statement to handle the term.

Usage
switch (Term) { case Label1: Statement1; ...; case LabelN: StatementN; default: DefaultStatement; }
Description
Finds the first LabelM term in the case list that unifies with Term, and executes the associated StatementM. If none of the case labels match, then executes the DefaultStatement associated with the default label. If there is no default label, then the switch statement fails.
Multiple case labels can be specified for the same statement with case Label1: case Label2: ... case LabelN: Statement. The default label can be mixed with regular case labels.
Unlike C/C++, execution does not fall through from StatementM to the following StatementM+1.
Once a LabelM is found that unifies with Term, the switch statement does an implicit commit/0 to commit the clause to that choice. Backtracking does not select later case labels even if they may have otherwise unified with Term.
Examples
 eval(Term, Answer) {
     switch (Term) {
         case X + Y: {
             eval(X, XAnswer);
             eval(Y, YAnswer);
             Answer is XAnswer + YAnswer;
         }
         case X - Y: {
             eval(X, XAnswer);
             eval(Y, YAnswer);
             Answer is XAnswer - YAnswer;
         }
         case X * Y: {
             eval(X, XAnswer);
             eval(Y, YAnswer);
             Answer is XAnswer * YAnswer;
         }
         case X / Y: {
             eval(X, XAnswer);
             eval(Y, YAnswer);
             Answer is XAnswer / YAnswer;
         }
         case -X: {
             eval(X, XAnswer);
             Answer is -XAnswer;
         }
         default: {
             if (number(Term))
                 Answer = Term;
             else
                 lookup_variable(Term, Answer);
         }
     }
 }

 eval(2 * x + y, Answer)
See Also
if, Formal syntax of switch statements

throw/1 - throws an error to an enclosing catch goal.

Usage
throw(Term)
Description
Throws a freshly renamed version of Term as an error to an enclosing catch/3 goal that matches Term. Plang will backtrack to the matching catch/3 goal and then execute the associated recovery goal.
Compatibility
Standard Prolog
See Also
catch/3

true/0 - always succeed.

Usage
true
Description
The true predicate always succeeds execution of the current goal.
Examples
 true                 succeeds
Compatibility
Standard Prolog
See Also
fail/0

while - repeatedly execute a statement while a condition is true.

Usage
while (Condition) Statement
while [UnbindVars] (Condition) Statement
Description
The while loop evaluates Condition at the beginning of each iteration. If Condition is true then Statement will be executed. Otherwise, the loop terminates. If Statement fails, then the loop will fail.
If UnbindVars is specified, then it contains a list of local variables that will be unbound at the beginning of each loop iteration before Condition is evaluated.
Examples
 X = 1; while (X <= 10) { stdout::writeln(X); X ::= X + 1; }
 X = 1; while [Y] (X <= 10) { Y is X * 2; stdout::writeln(Y); X ::= X + 1; }
See Also
do, for, Formal syntax of while statements

Generated on 26 May 2011 for plang by  doxygen 1.6.1