Go to the previous, next section.
By making use of the module systems facilities, programs can be divided into different modules. Each module has its own independent predicate name space. This is an important feature for the development of larger programs. The module system of SICStus Prolog is procedure based. This means that only the predicates are local to a module, whereas terms are global. The module system is flat, not hierarchical, so all modules are visible to one another. It is non-strict, i.e. the normal visibility rules can be overridden by special syntax. No overhead is incurred on compiled calls to predicates in other modules. It is modeled after and compatible with the Quintus Prolog module system. Finally, using the module system is optional, and SICStus Prolog may be used without the user being aware of the module system at all.
Modules in SICStus Prolog can also be used for object-oriented programming. See section Prolog Objects for details.
Each predicate in the Prolog system, whether built-in or user defined, belongs to a module. A predicate is generally only visible in the module where it is defined. However a predicate may be imported by another module. It is thereby made visible in that module too. Built-in predicates are visible in every module. Predicates declared as public in a module declaration (see below) are exported. Normally only public predicates may be imported by another module.
For any given goal, the source module is the module in which the corresponding predicate must be visible. Similarly, for any given clause, the source module of its head is the module into which the clause is loaded.
For goals occurring in a source file with a module declaration, the
source module is the declared module. For goals occurring in a source
file without a module declaration, the source module is the module that
the file is being loaded into. For goals typed at the top level, the
source module is the type-in module. The type-in module is by
default the user
module but may be changed by the built-in
predicate module/1
.
The other predefined module is the prolog
module where all the
built-in predicates reside. The exported built-in predicates are
automatically imported into each new module as it is created.
Notwithstanding the visibility rules, any predicate can be called from any other module by prefixing the goal with the module name and the colon operator, thus overriding the source module of the goal:
| ?- foo:bar(X).
This feature is intended mainly for debugging purposes, since it defies the purposes of the module system. If the prefixed goal is a meta-predicate, however, the prefixed module name may affect the module name expansion of the goal (see section Module Name Expansion).
It is also possible to override the source module of clauses and directives by module prefixing. For example,
:- dynamic mod:p/1. p(X) :- mod:(q(X), r(X)). mod:(q(X) :- r(X)). mod:s(X) :- t(X).
declares mod:p/1
as dynamic, whatever the source module is;
defines p/1
in the source module as calling mod:q/1
and
mod:r/1
; defines mod:q/1
as calling mod:r/1
; and
defines mod:s/1
as calling t/1
in the source module.
The latter technique is particularly useful when the prefix is
user
and the predicate is a "hook" predicate such as
user:portray/1
which must be defined in the user
module,
but the rest of the file consists of predicates belonging to some other
module.
A module is normally defined by putting a module declaration first in a source file.
:- module(ModuleName, PublicPredicateList).
When the file is loaded, all predicates in the file go into ModuleName and the predicates of the PublicPredicateList are exported. When a module declaration is processed, all existing predicates in the module are erased before the new ones are loaded. A file which contains a module declaration is henceforth called a module file.
A module can also be defined dynamically by asserting or loading predicates to it:
| ?- assert(m:p(x)).
creates the module m
, if it does not already exists, and asserts
p(x)
to it.
| ?- compile(m:f).
creates the module m
and loads f
into m
.
Dynamically created modules have no public predicates.
When a module file is loaded by one of the predicates consult/1
,
compile/1
, ensure_loaded/1
, use_module/1
, or
load/1
(See section Loading Programs), all the public predicates of the
module file are imported by the receiving module. In addition, the
built-in predicates use_module/(2-3)
may be used to specify which
predicates to import.
Clashes with already existing predicates, local or imported from other
modules, are handled in two different ways: If the receiving module is
the user
module, the user is asked for redefinition of the
predicate. For other receiving modules, a warning is issued and the
importation is canceled. In the first case redefinition silently takes
place if the flag redefine_warnings
has the value off
(see
prolog_flag/3
). The binding of an imported predicate remains,
even if the origin is reloaded or deleted. However, abolish/1
breaks up the importation binding. When a module file is reloaded, a
check is made that the predicates imported by other modules are still in
the public list. If that is not the case, a warning is issued. Note
that an imported predicate may be re-exported.
There is no error checking of module handling in Runtime Systems.
Some predicates take goals as arguments (i.e. meta-predicates). These
arguments must include a module specification stating which module the
goal refers. Some other predicates also need module information i.e.
compile/1
. The property of needing module information is
declared with a meta-declaration (see section Meta-Predicate Declarations). Goals for
these predicates are module name expanded to ensure the module
information. Goals issued at top level and goals appearing as directives
are expanded prior to execution while goals in the bodies of clauses are
expanded at compile time. The expansion is made by preceding the
relevant argument with `Module:'. If the goal is prefixed by
`Module:', Module is used for the expansion, otherwise
the source/type-in module is used. An argument is not expanded if:
1. It already has a module prefix. 2. It is a variable which appears in an expandable position in the head of the clause.
Some examples:
| ?- [user]. | :- meta_predicate p(:), q(:). | r(X) :- p(X). | q(X) :- p(X). | ^D {user consulted, 40 msec 1088 bytes} yes | ?- listing. r(A) :- p(user:A). q(A) :- p(A). yes
Here, p/1
and q/1
are declared as meta-predicates while
r/1
is not. Thus the clause r(X) :- p(X)
will be
transformed to r(X) :- p(M:X)
, by item 2 above, where
M is the type-in module, whereas q(X) :- p(X)
will not.
| ?- m:assert(f(1)).
Here, assert/1
is called in the module m
. However, this
does not ensure that f(1)
is asserted into m
. The fact
that assert/1
is a meta-predicate makes the system module name
expand the goal, transforming it to m:assert(m:f(1))
before
execution. This way, assert/1
is supplied the correct module
information.
The fact that a predicate needs module name expansion is declared in a meta-predicate declaration:
:- meta_predicate MetaPredSpec, @dots{}, MetaPredSpec.
where each MetaPredSpec is a mode spec. E.g.
:- meta_predicate p(:, +).
which means that the first argument of p/2
shall be module name
expanded. The arguments in the mode spec are interpreted as:
A number of built-in predicates have predefined meta-predicate
declarations, as indicated by the mode specs in this manual,
e.g. call(:Term)
.
Go to the previous, next section.