Quintus Prolog Manual


(PREV) (NEXT)

g-13: Modules

g-13-0: Overview

The module system lets the user divide large Prolog programs into modules , or rather smaller sub-programs, and define the interfaces between those modules. Each module has its own name space; that is, a predicate defined in one module is distinct from any predicates with the same name and arity which may be defined in other modules. The module system encourages a group of programmers to define the dependence each has on others' work before any code is written, and subsequently allows all to work on their own parts independently. It also helps to make library predicates behave as extensions of the existing set of built-in predicates. The Quintus Prolog library uses the module system and can therefore serve as an extended example of the concepts presented in the following text. The design of the module system is such that loading library files and calling library predicates can be performed without knowledge of the module system. Some points to note about the module system are that:

g-13-1: Basic Concepts

Each predicate in a program is identified by its module, as well as by its name and arity. A module defines a set of predicates, some of which have the property of being public. Public predicates are predicates which can be imported by other modules, which means that they can then be called from within those modules. Predicates which are not public are private to the module in which they are defined; that is, they cannot be called from outside that module (except by explicitly overriding the modularity rules as described in {manual(g-13-5)}). There are two kinds of importation:

  1. A module M1 may import a specified set of predicates from another module M2. All the specified predicates should be public in M2.
  2. A module M1 may import all the public predicates of another module M2.

Built-in predicates do not need to be imported; they are automatically available from within any module. There is a special module called 'user' which is used by default when predicates are being defined and no other module has been specified. If you are using a program written by someone else, you need not be concerned as to whether or not that program has been made into a module. The act of loading a module from a file using compile/1, or ensure_loaded/1 ({manual(g-4)}) will automatically import all the public predicates in that module. Thus the command

        :- ensure_loaded(library(basics)).

will load the basic list-processing predicates from the library and make them available.

g-13-2: Defining a Module

The normal way to define a module is by creating a module-file for it and loading it into the Prolog system. A module-file is a Prolog file that begins with a module declaration. A module declaration has the form

        :- module(+ModuleName, +PublicPredList).

Such a declaration must appear as the first term in a file, and declares that file to be a module-file. The predicates in the file will become part of the module ModuleName, and the predicates specified in PublicPredList are those which can be imported by other modules; that is, the public predicates of this module. Instead of creating and loading a module-file, it is also possible to define a module dynamically by, for example, asserting clauses into a specified module. A module created in this way has no public predicates; all its predicates are private. This means that they cannot be called from outside that module except by explicitly overriding the modularity rules as described in {manual(g-13-5)}. Dynamic creation of modules is described in more detail in {manual(g-13-8)}.

g-13-3: Converting Non-module-files into Module-files

The Prolog cross-referencer located in qlib<QP_version>/tools can automatically generate module/2 declarations from its cross-reference information. This is useful if you want to take a set of files making up a program and make each of those files into a module-file. See the file 'library(xref.doc)' for more information. Alternatively, if you have a complete Prolog program consisting of a set of source files {file1, file2, ...}, and you wish to encapsulate it in a single module mod, then this can be done by creating a "driver" file of the following form:

        :- module(mod, [ ... ]).

        :- ensure_loaded(file1).
        :- ensure_loaded(file2).
           .
           .
           .

When a module is created in this way, none of the files in the program {file1, file2, ...} have to be changed.

g-13-4: Loading a Module

To gain access to the public predicates of a module-file, load it as you would any other file -- using compile/1, or ensure_loaded/1 as appropriate. For example, if your code contains a directive such as

        :- ensure_loaded(File).

this directive will load the appropriate file File whether or not File is a module-file. The only difference is that if File is a module-file any private predicates which it defines will not be visible to your program. The load predicates are adequate for use at Prolog's top level, or when the file being loaded is a utility such as a library file. When you are writing modules of your own; use_module/[1,2,3] is the most useful. The following predicates are used to load modules:

Before a module-file is loaded, the associated module is reinitialized: any predicates previously imported into that module are forgotten by the module. If a module of the same name with a different PublicPredList or different meta-predicate list has previously been loaded from a different module-file, a warning is printed and you are given the option of abandoning the load. Only one of these two modules can exist in the system at one time. Normally, a module-file can be reloaded after editing with no need to reload any other modules. However, when a module-file is reloaded after its PublicPredList or its meta-predicate declaration (see {manual(g-13-16)}) has been changed, any modules that import predicates from it may have become inconsistent. This is because a module is associated with a predicate at compile time, rather than run time. Thus, other modules may refer to predicates in a module-file that are no longer public or whose module name expansion requirements have changed. In the case of module-importation (where all, rather than specific, public predicates of a module are imported), it is possible that some predicates in the importing module should now refer to a newly-public predicate but do not. Whenever the possibility of such inconsistency arises, you will be warned at the end of the load that certain modules need to be reloaded. This warning will be repeated at the end of each subsequent load until those modules have been reloaded. Modules may be saved to a QOF file by calling save_modules(Modules,File) (see {manual(g-5)}).

g-13-5: Visibility Rules

By default, predicates defined in one module cannot be called from another module. This section enumerates the exceptions to this -- the ways in which a predicate can be visible to modules other than the one in which it is defined.

  1. The built-in predicates can be called from any module.
  2. Any predicate which is named in the PublicPredList of a module, and which is imported by some other module M, can be called from within M.
  3. Module Prefixing: Any predicate, whether public or not, can be called from any other module if its module is explicitly given as a prefix to the goal, attached with the ':'/2 operator. The module prefix overrides the default module. For example,
  4.            :- mod:foo(X,Y).
    
        

    always calls foo/2 in module mod. This is effectively a loophole in the module system which allows you to override the normal module visibility rules. It is intended primarily to facilitate program development and debugging, and it should not be used extensively since it subverts the original purposes of using the module system. Note that a predicate called in this way does not necessarily have to be defined in the specified module. It may be imported into it. It can even be a built-in predicate, and this is sometimes useful -- see {manual(g-13-6)}, for an example.

g-13-6: The Source Module

For any given procedure call, or goal, the source module is the module in which the corresponding predicate must be visible. That is, unless the predicate is built-in it must be defined in, or imported into, the source module. For goals typed at the top level, the source module is the type-in module, which is 'user' by default -- see {manual(g-13-7)}. For goals appearing in a file (either as goal clauses or as normal clauses), the source module is the one into which that file has been loaded. There are a number of built-in predicates which take predicate specifications, clauses, or goals as arguments. Each of these types of argument must be understood with reference to some module. For example, assert/1 takes a clause as its argument, and it must decide into which module that clause should be asserted. The default assumption is that it asserts the clause into the source module. Another example is call/1. The goal (A) calls the predicate foo/1 in the source module; this ensures that in the compound goal (B) both occurrences of foo/1 refer to the same predicate.

call(foo(X))                                                              (A)

call(foo(X)), foo(Y)                                                      (B)

All predicates that refer to the source module allow you to override it by explicitly naming some other module to be used instead. This is done by prefixing the relevant argument of the predicate with the module to be used followed by a ':' operator. For example (C), asserts f(x) in module m.

| ?- assert(m:f(x)).                                                     (C)

Note that if you call a goal in a specified module, overriding the normal visibility rules (see {manual(g-13-5)}), then the source module for that goal is the one you specify, not the module in which this call occurs. For example (D), has exactly the same effect as (C) -- f(x) is asserted in module m. In other words, prefixing a goal with a module duplicates the effect of calling that goal from that module.

| ?- m:assert(f(x)).                                                     (D)

Another built-in predicate which refers to the source module is compile/1. In this case, the argument is a file, or list of files, rather than a predicate specification, clause, or goal. However, in the case where a file is not a module-file, compile/1 must decide into which module to compile its clauses, and it chooses the source module by default. This means that you can compile a file File into a specific module M using

        | ?- compile(M:File).

Thus if File is a module file, this command would cause its public predicates to be imported into module M. If File is a non-module file, it is loaded into module M. For a list of the built-in predicates that depend on the source module, see {manual(g-13-15)}. In some cases, user-defined predicates may also require the concept of a source module. This is discussed in {manual(g-13-16)}.

g-13-7: The Type-in Module

The type-in module is the module which is taken as the source module for goals typed in by the user. The name of the default type-in module is 'user'. That is, the predicates which are available to be called directly by the user are those which are visible in the module 'user'. When debugging, it is often useful to call, directly from the top level, predicates which are private to a module, or predicates which are public but which are not imported into 'user'. This can be done by prefixing each goal with the module name, as described in {manual(g-13-5)}; but rather than doing this extensively, it may be more convenient to make this module the type-in module. The type-in module can be changed using the built-in predicate module/1 ({manual(l-3)}); for example,

        | ?- module(mod).

This command will cause subsequent goals typed at the top level to be executed with 'mod' as their source module. The name of the type-in module is always displayed, except when it is 'user'. If you are running Prolog under the editor interface, the type-in module is displayed in the status line of the Prolog window. If you are running Prolog without the editor interface, the type-in module is displayed before each top-level prompt. For example, if you are running Prolog without the editor:

        | ?- module(foo).

        yes
        [foo]
        | ?-

It should be noted that it is unlikely to be useful to change the type-in module via a directive embedded in a file to be loaded, because this will have no effect on the load -- it will only change the type-in module for commands subsequently entered by the user.

g-13-8: Creating a Module Dynamically

There are several ways in which you can create a module without loading a module-file for it. One way to do this is by asserting clauses into a specified module. For example, the command (A) will create the dynamic predicate f/1 and the module m if they did not previously exist.

        | ?- assert(m:f(x)).                                             (A)

Another way to create a module dynamically is to compile a non-module-file into a specified module. For example (B), will compile the clauses in File into the module M.

        | ?- compile('M':File).                                          (B)

The same effect can be achieved by (temporarily) changing the type-in module to M (see {manual(g-13-7)}) and then calling 'compile(File)', or executing the command in module M as in (C).

        | ?- M:compile(File).                                            (C)

g-13-9: Module Prefixes on Clauses

Every clause in a Prolog file has a source module implicitly associated with it. If the file is a module-file, then the module named in the module declaration at the top of the file is the source module for all the clauses. If the file is not a module-file, the relevant module is the source module for the command which caused this file to be loaded. The source module of a predicate decides in which module it is defined (the module of the head), and in which module the goals in the body are going to be called (the module of the body). It is possible to override the implicit source module, both for head and body, of clauses and directives, by using prefixes. For example, consider the module file:

        :- module(a, []).

        :- dynamic m:a/1.
        b(1).
        m:c([]).
        m:d([H|T]) :- q(H), r(T).
        m:(e(X) :- s(X), t(X)).
        f(X) :- m:(u(X), v(X)).

In the previous example, the following modules apply:

  1. a/1 is declared dynamic in the module m.
  2. b/1 is defined in module a (the module of the file).
  3. c/1 is defined in module m.
  4. d/1 is defined in module m, but q/1 and r/1 are called in module a (and must therefore be defined in module a).
  5. e/1 is defined in module m, and s/1 and t/1 are called in module m.
  6. f/1 is defined in module a, but u/1 and v/1 are called in module m.

Module prefixing is especially useful when the module prefix is 'user'. There are several predicates which have to be defined in module 'user' but which you may want to define (or extend) in a program which is otherwise entirely defined in some other module or modules:

        runtime_entry/1
        term_expansion/2
        portray/1
        file_search_path/2
        library_directory/1

Note that if clauses for one of these predicates are to be spread across multiple files, it will be necessary to declare that predicate to be multifile by putting a multifile declaration in each of the files.

g-13-9-1: Current Modules

A loaded module becomes current as soon as it is encountered, and a module can never lose the property of being current.

g-13-10: Debugging Code in a Module

Having loaded a module to be debugged, you can trace through its execution in the normal way. When the debugger stops at a port, the procedure being debugged is displayed with its module name as a prefix unless the module is 'user'. The predicate spy/1 depends on the source module. It can be useful to override this during debugging. For example,

        | ?- spy mod1:f/3.

puts a spypoint on f/3 in module mod1. It can also be useful to call directly a predicate which is private to its module in order to test that it is doing the right thing. This can be done by prefixing the goal with its module; for example,

        | ?- mod1:f(a,b,X).

g-13-11: Modules and Loading through the Editor Interface

When you (re)load some Prolog code through the editor interface, the module into which the code is to be loaded is selected as follows.

Note that when a fragment of code has been loaded into a particular module other than 'user', the editor will subsequently insist that that code belongs to that module. In order to change this, the entire module must be reloaded. When a module declaration is processed, the module is reinitialized; all predicates previously imported into that module are forgotten. Therefore, when only part of a module-file is reloaded through the editor interface, that part should generally not include the module declaration. Loading an entire module through the editor interface is like loading the module via the Load Predicates in that all the public predicates in the module are imported into the type-in module. The only difference is that in the case in which you load the module through the editor interface you will be prompted for confirmation before the importation takes place. This is because there are situations in which you might want to reload a module via the editor interface without importing it into the type-in module; that is, situations in which you would not want to allow the importation to happen. For example, suppose that the type-in module is the default 'user', and that you have been modifying a module m1 from which another module m2 imports predicates, but from which 'user' does not import anything. In this case, you may want to reload m1, using the editor interface, without importing it into 'user'. When a file that is not a module-file is loaded into several different modules, reloading all or part of it through the editor interface affects only the module into which it was most recently loaded.

g-13-12: Name Clashes

ix(name clash) A name clash can arise if:

  1. a module tries to import a predicate from some other module m1 and it has already imported a predicate with the same name and arity from a module m2;
  2. a module tries to import a predicate from some other module m1 and it already contains a definition of a predicate with the same name and arity; or
  3. a module tries to define a predicate with the same name and arity as one that it has imported.

Whenever a name clash arises, a message is displayed which begins with the words "NAME CLASH". If the module that is importing or defining the clashing predicate is not 'user', then this message is just a warning, and the attempt to import or define the predicate simply fails. Otherwise, if the module is 'user', the user is asked to choose from one of several options; for example,

        NAME CLASH: f/3 is already imported into module user
                    from module m1;
                    do you want to override this definition with
                    the one in m2? (y,n,p,s,a or ?)

The meanings of the four recognized replies are as follows:

g-13-13: Obtaining Information about Loaded Modules

g-13-13-1: Predicates Defined in a Module

The built-in predicate current_predicate/2 can be used to find the predicates that are defined in a particular module. To backtrack through all of the predicates defined in module m, use

        | ?- current_predicate(_, m:Goal).

To backtrack through all predicates defined in any module, use

        | ?- current_predicate(_, M:Goal).

This succeeds once for every predicate in your program.

g-13-13-2: Predicates Visible in a Module

The built-in predicate predicate_property/2 can be used to find the properties of any predicate which is visible to a particular module. To backtrack through all of the predicates imported by module m, use

        | ?- predicate_property(m:Goal, imported_from(_)).

To backtrack through all of the predicates imported by module m1 from module m2, use

        | ?- predicate_property(m1:Goal, imported_from(m2)).

For example, you can load the 'basics' module from the library and then remind yourself of what predicates it defines like this:

        | ?- compile(library(basics)).
        [ ... loading messages ... ]

        yes
        | ?- predicate_property(P, imported_from(basics)).

        P = member(_2497,_2498) ;

        P = memberchk(_2497,_2498);
          .
          .
          .


This tells you what predicates are imported into the type-in module from 'basics'. You can also find all imports into all modules using

        | ?- predicate_property(M1:G, imported_from(M2)).

To backtrack through all of the predicates exported by module m, use

        | ?- predicate_property(m:Goal, exported).

There is a library package, library(show_module), which prints out information about current modules. For more information see {manual(k)}.

g-13-14: Importing Dynamic Predicates

Imported dynamic predicates may be asserted and retracted. For example, suppose the following file is loaded via use_module/1:

        :- module(m1, [f/1]).
        :- dynamic f/1.
        f(0).

Then f/1 can be manipulated as if it were defined in the current module. For example,

        | ?- clause(f(X), true).

        X = 0

The built-in predicate listing/1 distinguishes predicates which are imported into the current source module by prefixing each clause with the module name. Thus,

        | ?- listing(f).

        m1:f(0).

However, listing/1 does not prefix clauses with their module if they are defined in the source module itself. Note that

        | ?- listing.

can be used to see all the dynamic predicates defined in or imported into the current type-in module. And

        | ?- listing(m1:_).

can be used to see all such predicates which are defined in or imported into module m1.

g-13-15: Module Name Expansion

The concept of a source module is explained in {manual(g-13-6)}. For any goal, the applicable source module is determined when the goal is compiled rather than when it is executed. A procedure that needs to refer to the source module has arguments designated for module name expansion. These arguments are expanded at compile time by the transformation

        X -> M:X

where M is the name of the source module. For example, the goal call(X) is expanded into call(M:X) and the goal clause(Head, Body) is expanded into clause(M:Head, Body). Module name expansion is avoided if the argument to be expanded is already a ':'/2 term. In this case it is unnecessary since the module to be used has already been supplied by the programmer. The built-in predicates which use module name expansion, and the arguments requiring module name expansion are shown below. These arguments are labeled ' MOD' in the Arguments field of the reference page for each.



abolish(M:Pred)
abolish(M:Name, Arity)
assert(M:Term)
assert(M:Term, Ref)
asserta(M:Term)
asserta(M:Term, Ref)
assertz(M:Term)
assertz(M:Term, Ref)
bagof(T, M:P, S)
call(M:Goal)
check_advice(M:ListOfPredSpecs)
clause(M:Head, Body)
clause(M:Head, Body, Ref)
compile(M:Files)
consult(M:Files)
current_advice(M1:Goal, Port, M2:Action)
current_predicate(Name, M:Term)
debugger(Current, M:New)
ensure_loaded(M:Files)
findall(T, M:Pred, List)
initialization(M:Goal)
listing(M:List)
load_files(M:Files)
load_files(M:Files, Options)
load_foreign_files(M:Files, Libs)
multifile_assertz(M:Term)
nocheck_advice(M:ListOfPredSpecs)
nospy(M:List)
phrase(M:Phrase, S0)
phrase(M:Phrase, S0, S)
predicate_property(M:Goal, Property)
remove_advice(M:Goal, Port, Action)

retract(M:Term)
retractall(M:Term)
save_predicates(M:PredSpecs,File)
save_program(File,M:Goal)
setof(T, M:P, S)
source_file(M:Term,File)
source_file(M:PredSpec,ClauseNumber,File)
spy(M:List)
use_module(M:Files)
use_module(M:File, IL)
use_module(ExportModule, M:File, IL)
volatile(M:PredSpec)
X^(M:Goal)
[M:File|Rest]

In all of these predicates, M: can stand for multiple modules. It is the innermost module which is used in this case. For example, call(m1:m2:m3:p) calls m3:p/0.

g-13-16: The meta_predicate Declaration

Sometimes a user-defined predicate will require module name expansion (see {manual(g-13-15)}). This can be specified by providing a meta_predicate declaration for that procedure. Module name expansion is needed whenever the argument of a predicate has some module-dependent meaning. For example, if this argument is a goal that is to be called, it will be necessary to know in which module to call it -- or, if the argument is a clause to be asserted, in which module it should go. Consider, for example, a sort routine to which the name of the comparison predicate is passed as an argument. In this example, the comparison predicate should be called with respect to the module containing the call to the sort routine. Suppose that the sort routine is

         mysort(+CompareProc, +InputList, -OutputList)

An appropriate meta_predicate declaration for this is

         :- meta_predicate mysort(:, +, -).

The significant argument in the mysort/3 term is the ':', which indicates that module name expansion is required for this argument. This means that whenever a goal mysort(A, B, C) appears in a clause, it will be transformed at load time into mysort(M:A, B, C), where M is the source module. There are some exceptions to this compile-time transformation rule; the goal is not transformed if either of the following applies:

  1. A is of the form Module:Goal
  2. A is a variable and the same variable appears in the head of the clause in a module-name-expansion position.

The reason for 2 is that otherwise module name expansion could build larger and larger structures of the form Mn: ... :M2:M1:Goal. For example, consider the following program fragment adapted from the library (see library(samsort) for the full program):

        :- module(samsort, [samsort/3]).

        :- meta_predicate
                samsort(:, +, ?),
                sam_sort(+, :, +, +, ?).

        samsort(_, [], []) :- !.
        samsort(Order, List, Sorted) :-
                sam_sort(List, Order, [], 0, Sorted).
          .
          .
          .

Normally, the sam_sort/5 goal in this example would have the module name of its second argument expanded thus:

        sam_sort(List, samsort:Order, [], 0, Sorted)

because of the meta_predicate declaration. However, in this situation the appropriate source module will have already been attached to Order because it is the first argument of samsort/3 which also has a meta_predicate declaration. Therefore it is not useful to attach the module name (samsort) to Order in the call of sam_sort/5. The argument of a meta_predicate declaration can be a term, or a sequence of terms separated by commas. Each argument of each of these terms must be one of the following:

        :                       requires module name expansion
        non-negative integer    same as ':'
        +, -, *                 ignored

The reason for allowing a non-negative integer as an alternative to ':' is that this may be used in the future to supply additional information to the cross-referencer (library(xref)) and to the Prolog compiler. An integer n is intended to mean that that argument is a term which will be supplied n additional arguments. Thus, in the example above where the meta-argument is the name of a comparison routine which would be called with two arguments, it would be appropriate to write the integer 2 instead of a ':'. The reason for '+', '-' and '*' is simply so that the information contained in a DEC-10 Prolog-style 'mode' declaration may be represented in the meta_predicate declaration if you wish. There are many examples of meta_predicate declarations in the library.

g-13-17: Predicate Summary


Copyright (C) 1997 AI International Ltd
contact: product support sales information