12.1.2 Modules

Now, imagine that you are writing a program that needs two predicates, let's say pred1/2 and pred2/2. You have a definition for pred1 in the file preds1.pl and a definition of pred2 in the file preds2.pl. No problem, you think, I'll just load them into my program by putting

:- [preds1, preds2].

at the top of the file. Unfortunately, there seem to be problems this time. You get a message that looks something like the following:

  
{consulting /a/troll/export/home/MP/kris/preds1.pl...}
{/a/troll/export/home/MP/kris/preds1.pl consulted, 10 msec 296 bytes}
{consulting /a/troll/export/home/MP/kris/preds2.pl...}
The procedure helperpred/2 is being redefined.
    Old file: /a/troll/export/home/MP/kris/preds1.pl
    New file: /a/troll/export/home/MP/kris/preds2.pl
Do you really want to redefine it? (y, n, p, or ?) 

So what has happened? Well, it looks as if both files preds1.pl and preds2.pl are defining the predicate helperpred. And what's worse, you can't be sure that the predicate is defined in the same way in both files. So, you can't just say "yes, override", since pred1 depends on the definition of helperpred given in file preds1.pl and pred2 depends on the definition given in file preds2.pl. Furthermore, note that you are not really interested in the definition of helperpred at all. You don't want to use it. The predicates that you are interested in, that you want to use are pred1 and pred2. They need definitions of helperpred, but the rest of your program doesn't.

A solution to this problem is to turn preds1.pl and preds2.pl into modules. Here is what this means and how it works:

Modules essentially allow you to hide predicate definitions. You are allowed to decide which predicates should be public, i.e. callable from other parts of the program, and which predicates should be private, i.e. callable only from within the module. You will not be able to call private predicates from outside the module in which they are defined, but there will also be no conflicts if two modules internally define the same predicate. In our example. helperpred is a good candidate for becoming a private predicate, since it is only used as a helper predicate in the definition of pred1 and pred2.

You can turn a file into a module by putting a module declaration at the top of that file. Module declarations are of the form

:- module(ModuleName,List_of_Predicates_to_be_Exported

They specify the name of the module and the list of public predicates. That is, the list of predicates that one wants to export. These will be the only predicates that are accessible from outside the module.

So, by putting

:- module(preds1,[pred1/2]).

at the top of file preds1.pl you can define the module preds1 which exports the predicate pred1/2. And similarly, you can define the module preds2 exporting the predicate pred2/2 by putting

:- module(preds2,[pred2/3]).

at the top of file preds2.pl. helperpred is now hidden in the modules preds1 and preds2, so that there is no clash when loading both modules at the same time.

Modules can be loaded with the inbuilt predicate use_module/1. Putting :- use_module(preds1). at the top of a file will import all predicates that were defined as public by the module. That means, all public predicates will be accessible.

If you don't need all public predicates of a module, but only some of them, you can use the two-place version of use_module, which takes the list of predicates that you want to import as its second argument. So, by putting

:- use_module(preds1,[pred1/2]),
   use_module(preds2,[pred2/3]).

at the top of your file, you will be able to use pred1 and pred2. Of course, you can only import predicates that are also exported by the relevant module.


Patrick Blackburn, Johan Bos and Kristina Striegnitz
Version 1.2.5 (20030212)