How to call predicate in test that is called from outside of test?

As is, this has no clean solution in the plain SWI-Prolog module system. One possible option is to define ancestor/2 as a meta predicate and import it into the module that provides the parent/2 relation. That would look like

:- meta_predicate ancestor(:,?).

ancestor(M:A, B) :-
    ancestor(A,B,M).

ancestor(A,B,M) :-
    M:parent(A,B).
ancestor(A,C,M) :-
    M:parent(A,B),
    ancestor(B, C, M).

This is rather ugly. I’d probably go for

:- meta_predicate ancestor(2, ?, ?).

ancestor(Rel, A, B) :-
    call(Rel, A, B).
ancestor(Rel, A, C) :-
    call(Rel, A, B),
    ancestor(Rel, B, C).

After which you can rename ancestor to something like transitive_closure.

E.g., XSB has parameterized modules. Possibly SWI-Prolog should get these too at some time …

1 Like