Module System

## 4.10 Module System

- Overview
- Making a Module
- Using a Module
- Qualified Goals
- Exporting items other than Predicates

### 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.