Node:Operators, Next:Restrictions, Previous:Cut, Up:Prolog Intro

Operators in Prolog are simply a *notational convenience*.
For example, the expression `2+1`

could also be written
`+(2,1)`

. This expression represents the compound term

+ / \ 2 1

and *not* the number 3. The addition would only be performed if
the term were passed as an argument to an appropriate
predicate such as `is/2`

(see Arithmetic).

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 the
use of parentheses. The general rule is that it is the operator
with the *highest* precedence that is the principal
functor. Thus if `+`

has a higher precedence than
`/`

, then

a+b/c 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, i.e.

(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

Operators of type `xfx`

are not associative: it is a
requirement that both of the two subexpressions that 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 parenthesized (which gives it zero
precedence).

Operators of type `xfy`

are right-associative: only the first
(left-hand) subexpression must be of lower precedence; the
right-hand subexpression can be of the *same* precedence as
the main operator. Left-associative operators (type
`yfx`

) are the other way around.

A functor named `name` is declared as an operator of
type `type` and precedence `precedence` by the
directive:

:- op(precedence,type,name).

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. Note that the ISO Prolog standard contains a limitation that there should be no infix and postfix operators with the same name, however, SICStus Prolog lifts this restriction.

An operator of any kind may be redefined by a new
declaration of the same kind. This applies equally to
operators that are provided as standard, except for the `','`

operator. Declarations of all the standard operators
can be found elsewhere (see Standard Operators).

For example, the standard operators `+`

and `-`

are
declared by

:- op(500, yfx, [ +, - ]).

so that

a-b+c

is valid syntax, and means

(a-b)+c

i.e.

+ / \ - c / \ a b

The list functor `./2`

is not a standard
operator, but if we declare it thus:

:- op(900, xfy, .).

then `a.b.c`

would represent the compound term

. / \ a . / \ b c

Contrasting this with the diagram above for `a-b+c`

shows the
difference between `yfx`

operators where the tree grows to
the left, and `xfy`

operators where it grows to the right.
The tree cannot grow at all for `xfx`

operators; it is simply
illegal to combine `xfx`

operators having equal
precedences in this way.

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)`

.

If these precedence and associativity rules seem rather complex, remember that you can always use parentheses when in any doubt.

Note 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)).