- Documentation
- Reference manual
- Modules
- Why Use Modules?
- Defining a Module
- Importing Predicates into a Module
- Defining a meta-predicate
- Overruling Module Boundaries
- Interacting with modules from the top level
- Composing modules from other modules
- Operators and modules
- Dynamic importing using import modules
- Reserved Modules and using the `user' module
- An alternative import/export interface
- Dynamic Modules
- Transparent predicates: definition and context module
- Module properties
- Compatibility of the Module System
- Modules
- Packages
- Reference manual
6.13 Transparent predicates: definition and context module
The `module-transparent' mechanism is still underlying the actual implementation. Direct usage by programmers is deprecated. Please use meta_predicate/1 to deal with meta-predicates.
The qualification of module-sensitive arguments described in section 6.4 is realised using transparent predicates. It is now deprecated to use this mechanism directly. However, studying the underlying mechanism helps to understand SWI-Prolog's modules. In some respect, the transparent mechanism is more powerful than meta-predicate declarations.
Each predicate of the program is assigned a module, called its definition module. The definition module of a predicate is always the module in which the predicate was originally defined. Each active goal in the Prolog system has a context module assigned to it.
The context module is used to find predicates for a Prolog term. By default, the context module is the definition module of the predicate running the goal. For transparent predicates, however, this is the context module of the goal inherited from the parent goal. Below, we implement maplist/3 using the transparent mechanism. The code of maplist/3 and maplist_/3 is the same as in section 6.4, but now we must declare both the main predicate and the helper as transparent to avoid changing the context module when calling the helper.
:- module(maplist, maplist/3). :- module_transparent maplist/3, maplist_/3. maplist(Goal, L1, L2) :- maplist_(L1, L2, G). maplist_([], [], _). maplist_([H0|T0], [H|T], Goal) :- call(Goal, H0, H), maplist_(T0, T, Goal).
Note that any call that translates terms into predicates is
subject to the transparent mechanism, not just the terms passed to
module-sensitive arguments. For example, the module below counts the
number of unique atoms returned as bindings for a variable. It works as
expected. If we use the directive
:- module_transparent count_atom_results/3.
instead,
atom_result/2
is called wrongly in the module calling
count_atom_results/3.
This can be solved using strip_module/3
to create a qualified goal and a non-transparent helper predicate that
is defined in the same module.
:- module(count_atom_results, [ count_atom_results/3 ]). :- meta_predicate count_atom_results(-,0,-). count_atom_results(A, Goal, Count) :- setof(A, atom_result(A, Goal), As), !, length(As, Count). count_atom_results(_, _, 0). atom_result(Var, Goal) :- call(Goal), atom(Var).
The following predicates support the module-transparent interface:
- :- module_transparent(+Preds)
- Preds is a comma-separated list of name/arity pairs (like dynamic/1). Each goal associated with a transparent-declared predicate will inherit the context module from its parent goal.
- context_module(-Module)
- Unify Module with the context module of the current goal. context_module/1 itself is, of course, transparent.
- strip_module(+Term, -Module, -Plain)
- Used in module-transparent predicates or meta-predicates to extract the referenced module and plain term. If Term is a module-qualified term, i.e. of the format Module:Plain, Module and Plain are unified to these values. Otherwise, Plain is unified to Term and Module to the context module.