Before looking at other examples of recursion, it will be helpful to look at operators, because these are used in Prolog arithmetic. The basic arithmetic operations of addition, subtraction, multiplication etc., could be treated as predicates within the kind of Prolog style you have encountered so far. Addition, for example, might look like this:
+(X, Y, Z)
|
where X and Y are the arguments to be added, and Z is the result of the addition. Indeed, some Prologs allow you to do addition like this. Many more Prologs, however, define arithmetical operations in a way which is much more like the standard conventions, and write the above equation as
Z is X + Y
|
This is a novel format, because it writes the predicate symbols is and + between their arguments, without brackets. This is because these two symbols have been defined within Prolog as infix operators.
In working with operators, we need to pay attention to two factors: precedence and associativity.
In an expression with more than one operator, we need to know which operator to evaluate first. For example, the arithmetical expression 1 + 2 * 3 is potentially ambiguous. It could be (1 + 2) * 3 (i.e. 9), or 1 + (2 * 3) (i.e. 7). In fact, the convention in mathematics is to the latter: multiplication has precedence over addition. The * operator in Prolog is defined so that it too has precedence over the + operator.
Precedence involves the case where there are different operators in a single expression. Associativity involves multiple occurrences of the same operator. For example, 3 - 2 - 1 gives different results depending on whether it is treated as (3 - 2) - 1 (i.e. 0), or 3 - (2 - 1) (i.e. 2). In arithmetic it is the first order which is conventional: the left-most pair of numbers is evaluated first, then the next left-most, and so on. The subtraction operator is said to be left-associative.
Precedence and associativity are defined in Prolog with the built-in predicate op/3. The first argument determines precedence, the second associativity and the third defines the operator symbol. i.e.
op(Precedence,Associativity,Operator)
|
The associativity argument is also used to declare whether the operator is an infix operator (like the arithmetical ones), a prefix operator or a postfix operator.
The precedence argument is an integer. The principle is: the lower the number, the higher the precedence. In SWI
Prolog, the arithmetical operators have the following precedence values:
Operator | Precedence Value |
+ | 500 |
- | 500 |
* | 400 |
/ | 400 |
The conventions for defining the order (prefix, infix and postfix) and associativity (left, right, none) of operators are as
follows, where f stands for the position of the operator and x and y for its arguments:
Prefix | Postfix | Infix | Associativity |
fx | xf | xfx | none |
yf | yfx | left | |
fy | xfy | right | |
The occurrence of the argument symbol y indicates that an expression may contain multiple occurrences of the operator in question, and its position (left or right of f) indicates whether it is left or right associative.
The set of built-in operators and their properties can be explored by use of the built-in predicate current_op/3:
?- current_op(Precedence,Associativity,Operator).
Operator = sequential, Precedence = 1150, Associativity = fx ? yes |
Forcing Prolog to backtrack, producing further responses, by using semi-colon <return> will produce a complete listing of all the operators know to the system at the time the goal is posed.