Previous Up Next

4.10  Module System

4.10.1  Overview

The ECLiPSe module system controls the visibility of predicate names, syntax settings (structures, operators, options, macros), and non-logical store names (records, global variables). Predicates and syntax items can be declared local or they can be exported and imported. Store names are always local.

4.10.2  Making a Module

A source file can be turned into a module by starting it with a module directive. A simple module is:

:- module(greeting).
:- export hello/0.

hello :-
        who(X),
        printf("Hello %w!%n", [X]).

who(world).
who(friend).
This is a module which contains two predicates. One of them, hello/0 is exported and can be used by other modules. The other, who/1 is local and not accessible outside the module.

4.10.3  Using a Module

There are 3 ways to use hello/0 from another module. The first possibility is to import the whole ”greeting” module. This makes everything available that is exported from ”greeting”:

:- module(main).
:- import greeting.

main :-
        hello.
The second possibility is to selectively only import the hello/0 predicate:

:- module(main).
:- import hello/0 from greeting.

main :-
        hello.
The third way is not to import, but to module-qualify the call to hello/0:

:- module(main).

main :-
        greeting:hello.

4.10.4  Qualified Goals

The module-qualification using :/2 is also used to resolve name conflicts, i.e. in the case where a predicate of the same name is defined in more than one imported module. In this case, none of the conflicting predicates is imported - an attempt to call the unqualified predicate raises an error. The solution is to qualify every reference with the module name:

:- lib(ic).       % exports $>= / 2
:- lib(eplex).    % exports $>= / 2

    ..., ic:(X $>= Y), ...
    ..., eplex:(X $>= Y), ...
A more unusual feature, which is however very appropriate for constraint programming, is the possibility to call several versions of the same predicate by specifying several lookup modules:

    ..., [ic,eplex]:(X $>= Y), ...
which has exactly the same meaning as

    ..., ic:(X $>= Y), eplex:(X $>= Y), ...
Note that the modules do not have to be known at compile time, i.e. it is allowed to write code like

    after(X, Y, Solver) :-
        Solver:(X $>= Y).
This is however likely to be less efficient because it prevents compile-time optimizations.

4.10.5  Exporting items other than Predicates

The most commonly exported items, apart from predicates, are structure and operator declarations. This is done as follows:

:- module(data).
:- export struct(employee(name,age,salary)).
:- export op(500, xfx, reports_to).
...
Such declarations can only be imported by importing the whole module which exports them, i.e. using import data..
For more details see the User Manual chapter on Modules.

Previous Up Next