Operators in Prolog are simply a notational convenience.
For example, ``+`' is an infix operator, so

2 + 1

is an alternative way of writing the term `+(2, 1)`

.
That is, `2 + 1`

represents the data structure

+ / \ 2 1

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

; see ref-ari-eae.)

Prolog syntax allows operators of three 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 follows its single argument.

Each operator has a precedence, which is a
number from 1 to 1200. The precedence is used to disambiguate
expressions in which the structure of the term denoted is not made
explicit through the use of parentheses. 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 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 expression 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 required that
both of the arguments of the operator be subexpressions of
*lower* precedence than the operator itself; that is, the principal
functor of each subexpression must be of lower precedence, unless the
subexpression is
written in parentheses (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.

An atom named `Name` is declared as an
operator of type `Type` and precedence `Precedence` by the command

:-op(Precedence, Type, Name).

An operator declaration can be cancelled by redeclaring the `Name`
with the same `Type`, but `Precedence` 0.

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: infix, prefix, or postfix. Note that the ISO Prolog standard contains the restriction 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 for all these built-in operators can be found in
ref-syn-ops-bop.
For example, the built-in operators ``+`' and ``-`' are as if they
had been declared by (A) so that (B) is valid syntax, and means (C) or pictorially (D).

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

a-b+c (B)

(a-b)+c (C)

+ / \ - c / \ a b (D)

The list functor `./2`

is not a standard operator, but we could declare it
to be (E) and then (F) would represent the structure (G).

:-op(600, xfy, .). (E)

a.b.c (F)

. / \ a . / \ b c (G)

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.

Send feedback on this subject.