Meaning of instantiation mode indicators in arguments of Prolog predicates

Mode declarations first appeared in the DECsystem-10 compiler in the end of the 1970s. The DECsystem-10 user's guide of 1978-09 being one of the first descriptions. The motivation is given 1982-11-10:

Such information enables the compiler to generate more compact code making better use of runtime storage. The saving of runtime storage in particular can often be very substantial. Mode declarations also help other people to understand how your program operates.

DECsystem-10

+ — the argument will always be a NON-variable

- — the argument will always be a variable

? — no restriction

Note that these declarations apply to each goal. Most notably, they apply to recursive goals. In this manner the following mode declaration plus its definition implies that the second argument is not a partial list. Thus, a goal member(A, [c|_]) would be not conforming. So the interface and the implementation are somewhat interdependent which can lead to quite complex cases, when unifications performed by the predicate itself have to be taken into account.

:- mode member(?, +).
member(X, [X|_]). % member(X, [X,.._]) in DEC10
member(X, [_|L]) :-
   member(X, L).

In case a mode declaration is violated by a concrete goal, the declaration is either ignored, or will produce an error which at that time meant writing out an error message and failing. The DECsystem-10 interpreter always ignored the declarations.

Deep down in the 1970s, the DEC 10 User's guide thus gave rise of two interpretations to mode declarations: The first being the prescriptive one that does produce errors in case the modes are not met by a caller. The second one being entirely informal, ignoring the mode declarations at runtime. The former is used within the Prolog standard, the latter is found in the documentation of some Prolog systems.

ISO/IEC-Prolog: Template and modes subclause

The Prolog standard (ISO/IEC 13211-1:1995, 2007, 2012) uses the following format for the definition of built-in predicates. It starts with subclause .1 Description, .2 Template and modes, .3 Errors, and optionally continues with .4 Examples, .5 Bootstrapped built-in predicate(s).

8.1.2 Template and modes

A specification for both the type of arguments and which
of them shall be instantiated for the built-in predicate to
be satisfied. The cases form a mutually exclusive set.

...

The concretes modes are:

+ — the argument shall be instantiated.

@ — like + and the argument shall remain unaltered.

- — the argument shall be a variable that will be instantiated iff the goal succeeds.

? — no mode requirement, the argument may be a variable or an instantiated.

If a predicate was called with a differing mode, an instantiation_error or uninstantiation_error is produced. If the type does not match, a type_error is produced. In this manner the programmer can anticipate many errors simply by looking at the Template and mode subclause without reading the detailed error conditions.

Other systems

Systems that differ from ISO also differ to each other in their precise interpretation of modes. Many perform silent failure in case when a type error would be appropriate. They view mode declarations as a means to indicate cases where the predicate is expected to work with undefined meaning otherwise. Often the - is interpreted roughly as follows. Since there is no actual reference that defines the meaning, this is what I gathered informally:

- — the argument is an "output argument". Meaning that it will be unified with the resulting term after the goal has been executed. So the argument is steadfast. Often, no error is associated with such an argument.


Those prefix operators, in this context, represent instantiation modes, i.e. they tell you which arguments should be variables or instantiated when calling the predicate. They also tell you if an argument will be (possibly further) instantiated by the call. They can also be used to tell you that an argument is going to be meta-interpreted in some way by the predicate you're calling. Some of these instantiation modes are standard, other depend on the system. The most usual are:

- - the argument should be unbound (likely output argument)

+ - the argument should be bound (input argument)

? - the argument can be either bound or unbound

@ - the argument will not be further instantiated by the call

: - the argument will be meta-interpreted in some way (often ambiguous)

0 - the argument will be interpreted as goal and called as such

N - where N is natural number; the argument will be interpreted as a closure that will be composed with N additional arguments to construct a goal that will be called

Different systems provide other or different instantiation modes. For example, for stating that an argument should be ground when calling a predicate, or for stating that an argument should be a predicate indicator or that will be interpreted as a grammar rule body. You will need to refer to the documentation of the Prolog system you're using for the details.