4.24 Operators

Operators are defined to improve the readability of source code. For example, without operators, to write 2*3+4*5 one would have to write +(*(2,3),*(4,5)). In Prolog, a number of operators have been predefined. All operators, except for the comma (,) can be redefined by the user.

Some care has to be taken before defining new operators. Defining too many operators might make your source `natural' looking, but at the same time make it hard to understand the limits of your syntax. To ease the pain, as of SWI-Prolog 3.3.0, operators are local to the module in which they are defined. Operators can be exported from modules using a term op(Precedence, Type, Name) in the export list as specified by module/2. This is an extension specific to SWI-Prolog and the recommended mechanism if portability is not an important concern.

The module table of the module user acts as default table for all modules and can be modified explicitly from inside a module to achieve compatibility with other Prolog systems:

:- module(prove,
          [ prove/1
          ]).

:- op(900, xfx, user:(=>)).

Unlike what many users think, operators and quoted atoms have no relation: defining an atom as an operator does not influence parsing characters into atoms, and quoting an atom does not stop it from acting as an operator. To stop an atom acting as an operator, enclose it in parentheses like this: (myop).

[ISO]op(+Precedence, +Type, :Name)
Declare Name to be an operator of type Type with precedence Precedence. Name can also be a list of names, in which case all elements of the list are declared to be identical operators. Precedence is an integer between 0 and 1200. Precedence 0 removes the declaration. Type is one of: xf, yf, xfx, xfy, yfx, fy or fx. The `f' indicates the position of the functor, while x and y indicate the position of the arguments. `y' should be interpreted as ``on this position a term with precedence lower or equal to the precedence of the functor should occur''. For `x' the precedence of the argument must be strictly lower. The precedence of a term is 0, unless its principal functor is an operator, in which case the precedence is the precedence of this operator. A term enclosed in parentheses ( ... ) has precedence 0.

The predefined operators are shown in table 5. Operators can be redefined, unless prohibited by one of the limitations below. Applications must be careful with (re-)defining operators because changing operators may cause (other) files to be interpreted differently. Often this will lead to a syntax error. In other cases, text is read silently into a different term which may lead to subtle and difficult to track errors.

In SWI-Prolog, operators are local to a module (see also section 5.8). Keeping operators in modules and using controlled import/export of operators as described with the module/2 directive keep the issues manageable. The module system provides the operators from table 5 and these operators cannot be modified. Files that are loaded from the SWI-Prolog directories resolve operators and predicates from this system module rather than user, which makes the semantics of the library and development system modules independent of operator changes to the user module.

1200xfx-->, :-
1200fx:-, ?-
1150fxdynamic, discontiguous, initialization, meta_predicate, module_transparent, multifile, thread_local, volatile
1100xfy;, |
1050xfy->, *->
1000xfy,
900fy\+
900fx~
700xfx<, =, =.., =@=, =:=, =<, ==, =\=, >, >=, @<, @=<, @>, @>=, \=, \==, is
600xfy:
500yfx+, -, /\, \/, xor
500fx?
400yfx*, /, //, rdiv, <<, >>, mod, rem
200xfx**
200xfy^
200fy+, -, \
Table 5 : System operators
[ISO]current_op(?Precedence, ?Type, ?:Name)
True if Name is currently defined as an operator of type Type with precedence Precedence. See also op/3.