SWI-Prolog Source Documentation Version 2
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • SWI-Prolog Source Documentation Version 2
        • Introduction
        • Overview
        • Structured comments
        • File (module) comments
        • Type, mode and determinism declaration headers
        • Tags: @see, etc.
        • Wiki notation
        • Directory indices
        • Documentation files
        • Running the documentation system
        • Motivation of choices
        • Compatibility and standards

5 Type, mode and determinism declaration headers

Many predicates can sensibly be called in different ways, e.g. with a specific argument as input or as output. The header of the documentation of a predicate consists of one or more templates, each representing a specific way of calling the predicate.

A template can contain information about types, argument instantiation patterns, determinism and more. The syntax is informally described below:

<template> ::=<head>['//']’is' <determinism>
|<head>['//']
<determinism> ::=’det'
|’semidet'
|’failure'
|’nondet'
|’multi'
|’undefined'
<head> ::=<functor>’('<argspec> ’,' <argspec>’)'
|<functor>
<argspec> ::=[<instantiation>]<argname>[':'<type>]
<instantiation> ::=’++' | ’+' | ’-' | ’--' | ’?' | ’:' | ’@' | ’!'
<type> ::=<term>

The determinism values originate from Mercury. Their meaning is explained in the table below. Informally, det is used for deterministic transformations (e.g. arithmetic), semidet for tests, nondet and multi for generators. The failure indicator is rarely used. It mostly appears in hooks or the recovery goal of catch/3.

DeterminismPredicate behaviour
det Succeeds exactly once without a choice point
semidet Fails or Succeeds exactly once without a choice-point
failure Always fails
nondet No constraints on the number of times the predicate succeeds and whether or not it leaves choice-points on the last success.
multi As nondet, but succeeds at least one time.
undefined Well founded semantics third value. See undefined/0.

The meanings of the instantiation patterns for individual arguments are:

++Argument is ground at call-time, i.e., the argument does not contain a variable anywhere.
+Argument is fully instantiated at call-time, to a term that satisfies the type. This is not necessarily ground, e.g., the term [_] is a list, although its only member is unbound.
-Argument is an output argument. It may be unbound at call-time, or it may be bound to a term. In the latter case, the predicate behaves as if the argument was unbound, and then unified with that term after the goal succeeds. For example, the goal findall(X, Goal, [T]) is good style and equivalent to findall(X, Goal, Xs), Xs = [T]3The ISO standard dictates that findall(X, Goal, 1) raises a type_error exception, breaking this semantic relation. SWI-Prolog does not follow the standard here. Determinism declarations assume that the argument is a free variable at call-time. For the case where the argument is bound or involved in constraints, det effectively becomes semidet, and multi effectively becomes nondet.
--Argument is unbound at call-time. Typically used by predicates that create‘something' and return a handle to the created object, such as open/3 which creates a stream.
?Argument is bound to a partial term of the indicated type at call-time. Note that a variable is a partial term for any type.
:Argument is a meta-argument. Implies +.
@Argument will not be further instantiated than it is at call-time. Typically used for type tests.
!Argument contains a mutable structure that may be modified using setarg/3 or nb_setarg/3.

Users should be aware that calling a predicate with arguments instantiated in a way other than specified by one of the templates may result in errors or unexpected behavior.

Developers should ensure that predicates are steadfast with respect to output arguments (marked - in the template). This means that instantiation of output arguments at call-time does not change the semantics of the goal (it may be used for optimization, though). If this steadfast behavior cannot be guaranteed, -- should be used instead.

In the current version, argument types are represented by an arbitrary term without formal semantics. In future versions we may adopt a formal type system that allows for runtime verification and static type analysis Hermenegildo, 2000, Mycroft & O'Keefe, 1984, Jeffery et al., 2000

Examples

%!      length(+List:list, -Length:int) is det.
%!      length(?List:list, -Length:int) is nondet.
%!      length(?List:list, +Length:int) is det.
%
%       True if List is a list of length Length.
%
%       @compat iso