module_closure/2 — creates a module closure
module_closure/3 — creates a module closure for the specified procedure
:- module_closure(Name, Arity, Procedure) . :- module_closure(Name, Arity) .
For some Prolog procedures, it is essential to know the module within which they are invoked. For example,
setof/3 must invoke the goal in its second argument relative to the correct module. The problem is that
setof/3 is defined in
module builtins, while it may invoked in some other module which is where the code defining the goal in the second argument should be run. In reality,
setof/3 is defined as the module closure of another predicate
setof/4 (whose definition appears in the
builtins module). The extra argument to
setof/4 is the module in which the goal in the second argument of
setof/3 is to be run. Declaring
setof/3 to be a module closure of
setof/4 means that goals of the form
..., setof(X, G, L), ...
are automatically expanded to goals of the form
..., setof(M, X, G, L), ...
M is the current module; i.e., the module in which the original call took place. Thus
setof/4 is supplied with the correct module
M in which to run the goal in the second argument of the original call to
The actual predicate that you write should expect to receive the calling module as its first argument. Then one ‘ closes ‘ the predicate with a module closure declaration which suppresses the first(module) argument. The arguments to
module_closure/3 are as follows :
Nameis the name of the procedure the user will call.
Arityis the number of arguments of the user procedure; that is, the number of arguments in the ‘closed’ procedure which the user procedure will call.
Procedureis the name of the(unclosed) procedure to call with the additional module argument. Note that
Procedurecan be different than
Name, although they are often the same.
The procedure that the user will call should be exported if it is contained within a module. The actual (unclosed) procedure does not need to be exported.
module_closure/2 simply identifies the first and third arguments of
module_closure/3. That is, the command
:- module_closure(foo, 5) .
is equivalent to
:- module_closure(foo, 5, foo) .
The following example illustrates the use of
module_closure/3. First assume that the following three modules and code have been created and loaded :
module m1. use m3. export testA/1. testA(X) :- leading(X) . p(tom). p(dick). p(harry). endmod. % m1 module m2. use m3. export testB/1. testB(X) :- leading(X) . p(sally). p(jane). p(martha). endmod. % m2 module m3. leading(X) :- p(X) . endmod. % m3
Attempting to run either testA or testB in default module
user fails :
?- testA(X). no. ?- testB(X). no.
This is because the call to p(X) runs in module m3 which has no clauses defining
p/1. Now let us change module m3 to read as follows :
module m3. first(M, X) :- M:p(X). export leading/1. :- module_closure(leading, 1, first) . endmod.
We have defined a new predicate
first/2 which carries a module as its first argument and which makes the call to
p(X) in that module. And we have specified that
leading/1 is the module closure of
first/2. Now the calls succeed :
?- testA(X). X=tom yes. ?- testB(X). X=sally yes.
Note that we exported
module m3, and both
module m1 and
module m2 were declared to use