The YAP Module system

The YAP Predicate Module System.

The YAP module system is based on the Quintus/SISCtus module system quintus . In this design, modules are named collections of predicates, and all predicates belong to a single module. By default, predicates are only visible within a module, or private to that module. The module may also define a list of predicates that are exported, that is, visible to other modules.

The main predicates in the module system are:

  • module_50 "module/2" associates a source file to a module. It has two arguments: the name of the new module, and a list of predicates exported by the module.

  • @ref use_module_49 @"use_module/1" and @ref use_module_50 @"use_module/2" can be used to load a module. They take as first argument the source file for the module. Whereas @ref use_module_49 @"use_module/1" loads all exported predicates, @ref use_module_50 @"use_module/2" only takes the ones given by the second argument.

YAP pre-defines a number of modules.

  • Most system predicates belong to the module prolog. Predicates from the module prolog are automatically visible to every module.
  • The system module was introduced for SWI-Prolog compatibility, and in YAP mostly acts as an alias to prolog.
  • The user module is also visible to all other modules.

The YAP engine is always associated to a module, the current source module or type-in module. By default, all predicates read-in and all calls to a goal will be made to predicates visible to the current source module, Initially, the source module for YAP is the module user. Thus Prolog programs that do not define modules will operate within the user module. In this case, all predicates will be visible to all source files.

YAP includes a number of libraries and packages, most of them defining their own modules. Note that there is no system mechanism to avoid clashes between module names, so it is up to the programmer to carefully choose the names for her own program modules.

The main mechanism to change the current type-in module is by using the @ref module_50 @"module/2" declaration.This declaration sets the source module when it starts consulting a file, and resets it at the end. One can set the type-in module permanently by using the built-in \@ref module_49 \@"module/1".

@subsection autotoc_md0 Explicit Naming

The module system allows one to explicitly specify the source mode for a clause by prefixing a clause with its module, say: @icode user:(a :- b).
@endicode

it is also possible to type

@icode

user:a :- user:b.

@endicode

both formulations describe the same clause, independently of the current type-in module.

In fact, it is sufficient to specify the source mode for the clause's head:

@icode user:a :- b. @endicode

if the current type-in module is m, the clause could also be written as:

@icode user:a :- m:b. @endicode

The compiler rewrites the source clauses to ensure that explicit calls are respected, and that implicit calls are made to the current source module.

A goal should refer to a predicate visible within the current type-in module. Thus, if a goal appears in a text file with a module declaration, the goal refers to that module's context (but see the @ref initialization_49 @"initialization/1" directive for more details).

Again, one can override this rule by prefixing a goal with a module to be consulted. The following query:

@icode ?- nasa:launch(apollo,13). @endicode invokes the goal launch(apollo,13) as if the current source module was nasa.

YAP and other Prolog systems allow the module prefix to see all predicates visible in the module, including predicates private to the module. This rule allows maximum flexibility, but it also breaks encapsulation and should be used with care. The ciao language proposes a different approach to this problem, see @cite DBLP:conf/cl/GrasH00 .

Modules are not always associated with a source-file. They may range over several files, by using the includedirective. Moreover, they may not be associated to any source file. As an example, @icode ?- assert( nasa:launch(apollo,13) ). @endicode will create a module nasa, if does not already exist. In fact it is sufficient to call a predicate from a module to implicitly create the module. Hence after this call:

@icode ?- nasa:launch(apollo,13). @endicode

there will be a nasamodule in the system, even if nasa: @ref launch_50 @"launch/2" is not at all defined.