SWI-Prolog 5.6.53 Reference Manual: Section 5.10

## 5.10 Compatibility of the Module System

The principles behind the module system of SWI-Prolog differ in a number of aspects from the Quintus Prolog module system.

- The SWI-Prolog module system allows the user to redefine system predicates.
- All predicates that are available in the `system` and `user` modules are visible in all other modules as well.
- Quintus has the `meta_predicate/1' declaration were SWI-Prolog has the module_transparent/1 declaration.
- Operator declarations are local to a module and may be exported.

The meta_predicate/1 declaration causes the compiler to tag arguments that pass module sensitive information with the module using the :/2 operator. This approach has some disadvantages:

- Changing a meta_predicate declaration implies all predicates calling the predicate need to be reloaded. This can cause serious consistency problems.
- It does not help for dynamically defined predicates calling module sensitive predicates.
- It slows down the compiler (at least in the SWI-Prolog architecture).
- At least within the SWI-Prolog architecture the run-time overhead is larger than the overhead introduced by the transparent mechanism.

Unfortunately the transparent predicate approach also has some disadvantages. If a predicate A passes module sensitive information to a predicate B, passing the same information to a module sensitive system predicate both A and B should be declared transparent. Using the Quintus approach only A needs to be treated special (i.e., declared with meta_predicate/1)71Although this would make it impossible to call B directly.. A second problem arises if the body of a transparent predicate uses module sensitive predicates for which it wants to refer to its own module. Suppose we want to define findall/3 using assert/1 and retract/172The system version uses recordz/2 and recorded/3.. The example in figure 6 gives the solution.

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

    :- dynamic
            solution/1.

    :- module_transparent
            findall/3,
            store/2.

    findall(Var, Goal, Bag) :-
            assert(findall:solution('$mark')),
            store(Var, Goal),
            collect(Bag).

    store(Var, Goal) :-
            Goal,                   % refers to context module of
                                    % caller of findall/3
            assert(findall:solution(Var)),
            fail.
    store(_, _).

    collect(Bag) :-
            ...,

Figure 6 : findall/3 using modules

### 5.10.1 Emulating meta_predicate

The Quintus meta_predicate/1 directive can in many cases be replaced by the transparent declaration. Below is the definition of meta_predicate/1 as available from `library(quintus)`.

    :- op(1150, fx, (meta_predicate)).

    meta_predicate((Head, More)) :- !,
            meta_predicate1(Head),
            meta_predicate(More).
    meta_predicate(Head) :-
            meta_predicate1(Head).

    meta_predicate1(Head) :-
            Head =.. [Name|Arguments],
            member(Arg, Arguments),
            module_expansion_argument(Arg), !,
            functor(Head, Name, Arity),
            module_transparent(Name/Arity).
    meta_predicate1(_).             % just a mode declaration

    module_expansion_argument(:).
    module_expansion_argument(N) :- integer(N).

The discussion above about the problems with the transparent mechanism show the two cases in which this simple transformation does not work.