Operators
Operators in Prolog are simply a notational convenience.
For example, the expression
2 + 1
could also be written +(2,1).
It should be noticed that this expression represents the structure
and not the number 3.
The addition would only be performed if the structure was passed as an
argument to an appropriate procedure (such as eval/2 — see Section ).
The Prolog syntax caters for operators of three main kinds —
infix, prefix and postfix.
An infix operator appears between its two arguments, while a prefix operator
precedes its single argument and a postfix operator is written after its
single argument.
Each operator has a precedence, which is a number from 1 to 1200.
The precedence is used to disambiguate
expressions where the structure of the term denoted is not made
explicit through parenthesization.
The general rule is that the operator with the
highest precedence is the principal functor.
Thus if `+' has a higher precedence than `/', then a+b/c and a+(b/c)
are equivalent and denote the term +(a,/(b,c)).
Note that the infix form of the term /(+(a,b),c)
must be written with explicit parentheses, (a+b)/c.
If there are two operators in the subexpression having the same
highest precedence, the ambiguity must be resolved from the types of
the operators.
The possible types for an infix operator are
xfx xfy yfx
With an operator of type `xfx', it is a requirement that both of the
two subexpressions which are the arguments of the operator must be of
lower precedence than the operator itself, i.e. their principal
functors must be of lower precedence, unless the subexpression is
explicitly bracketed (which gives it zero precedence).
With an operator of type `xfy', only the first or left-hand subexpression must
be of lower precedence; the second can be of the same precedence as
the main operator; and vice versa for an operator of type `yfx'.
For example, if the operators `+' and `–' both have type `yfx'
and are of the same precedence, then the expression
``a–b+c'' is valid, and means ``(a–b)+c'', i.e. ``+(–(a,b),c)''.
Note that the expression would be invalid if the operators had type
`xfx', and would mean ``a–(b+c)'', i.e. ``–(a,+(b,c))'',
if the types were both `xfy'.
The possible types for a prefix operator are
fx fy
and for a postfix operator they are
xf yf
The meaning of the types should be clear by analogy with those for
infix operators.
As an example, if `not' were declared as a prefix
operator of type `fy', then
not not P
would be a permissible way to write not(not(P)).
If the type were `fx', the preceding expression would not be legal, although
not P
would still be a permissible form for not(P).
In SB-Prolog, a functor named name is declared as an
operator of type type and precedence precedence by calling
the evaluable predicate op:
| ?- op(precedence, type, name).
op/3 (L)
The argument name can also be a list of names of operators of the same
type and precedence.
It is possible to have more than one operator of the same name,
so long as they are of different kinds, i.e. infix, prefix or postfix.
An operator of any kind may be redefined by a new declaration of the same kind.
This applies equally to operators which are provided as
standard in SB-Prolog, namely the ones shown in Table .
Table:
Operator Priorities
:– op( |
1200, |
xfx, |
[ :–, –> ]). |
:– op( |
1200, |
fx, |
[ :– ]). |
:– op( |
1198, |
xfx, |
[ ::– ]). |
:– op( |
1150, |
fy, |
[ mode, public, dynamic ]). |
:– op( |
1100, |
xfy, |
[ ; ]). |
:– op( |
1050, |
xfy, |
[ –> ]). |
:– op( |
1000, |
xfy, |
[ ',' ]). /* See note below */ |
:– op( |
900, |
fy, |
[ not,
\ +, spy, nospy ]). |
:– op( |
700, |
xfx, |
[ =, is, =.., ==,
\ = =, @<, @>, @= <, @> =, |
|
|
|
=:=,
= \ =, <, >, = <, > =, ?=,
\ = ]). |
:– op( |
661, |
xfy, |
[ `.' ]). |
:– op( |
500, |
yfx, |
[ +, –, /
\,
\/ ]). |
:– op( |
500, |
fx, |
[ +, – ]). |
:– op( |
400, |
yfx, |
[ *, /, //, «, » ]). |
:– op( |
300, |
xfx, |
[ mod ]). |
:– op( |
200, |
xfy, |
[ ˆ ]). |
|
Operator declarations are most usefully placed in directives at the top
of your program files.
In this case the directive should be a command as shown above.
Another common method of organization is to have one file
just containing commands to declare all the necessary operators.
This file is then always consulted first.
Note that a comma written literally as a punctuation character
can be used as though it were an infix operator of precedence 1000 and
type `xfy':
X,Y ','(X,Y)
represent the same compound term.
But note that a comma written as a quoted atom is not a standard operator.
Note also that the arguments of a compound term written in
standard syntax must be expressions of precedence below 1000.
Thus it is necessary to parenthesize the expression P :– Q in
assert((P :- Q))
The following syntax restrictions serve to remove
potential ambiguity associated with prefix operators.
- In a term written in standard syntax, the principal functor and
its following (must not be separated by any whitespace.
Thus
point (X,Y,Z)
is invalid syntax (unless point were declared as a prefix operator).
- If the argument of a prefix operator starts with a (, this (
must be separated from the operator by at least one space or other
non-printable character.
Thus
:-(p;q),r.
(where :– is the prefix operator) is invalid syntax,
and must be written as
:- (p;q),r.
- If a prefix operator is written without an argument, as an ordinary atom,
the atom is treated as an expression of the same precedence
as the prefix operator, and must therefore be bracketed where necessary.
Thus the brackets are necessary in
X = (?-)