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 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:

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.