drt24 / gnuprologjava

GNU Prolog for Java
8 stars 5 forks source link

Now that we have modules, implement meta_predicate directive #16

Closed thetrime closed 6 years ago

thetrime commented 8 years ago

To see why this is necessary, consider the following:

:-module(a, []).

foo:-
   findall(X, some_goal(X), Xs, []).

some_goal(a).
some_goal(b).

Suppose that findall/4 (a variation on findall/3 where the last two args are a difference list) is defined, rather hurriedly, in module(b):

:-module(b, [findall/4]).

findall(A,B,C,D):-
   findall(A,B,T),
   another_goal,
   append(C, D, T).

When we first call findall/4 from module(a), we compile a linking shim like this:

a:findall(A,B,C,D):- b:findall(A,B,C,D).

But when we execute this, we get the exception that some_goal/1 is not defined, since we're looking for it in module(b). If we don't change the context to b when executing code exported from b, then findall/4 will complain it cannot find another_goal/0. In other words, logically we have to be able to tell the compiler that what we really want is this:

a:findall(A,B,C,D):- b:findall(A,a:B,C,D).

The way this works in SWI-Prolog, YAP, SICStus and Quintus is to use a declaration like (the specifics vary by system)

:-meta_predicate(findall(?, 0, -, ?)).
thetrime commented 6 years ago

I think this was fixed in April 2016 with the merge. Closing.