Term_expansion not applied

I’m struggling with a simple example of term_expansion. I seems to be missing a trick, or simply having a brain fart.

:- module(scratch,[
        z/2,
        x/1
    ]).

term_expansion(q(A,B), z(B,A)).

q(1,2).      % ==>  z(2,1).

x(q(1,2)).   % ==>   x(z(2,1)).
?- use_module(scratch).
true.

?- scratch:q(X,Y).
ERROR: Unknown procedure: scratch:q/2 (DWIM could not correct goal)  % Expected

?- scratch:z(2,1).
true.

So far so good. But,

?- scratch:x(X).
X = q(1, 2).          % X = z(2,1) expected.

Am I right in thinking that q(A,B) is a Term in both q(1,2). and x(q(1,2)).? So why isn’t the replacement x(q(1,2)) => x(z(2,1)). applied?

I thought that perhaps term_expansion applies only to the clauses asserted during consultion (and not their subcomponent terms) – however, the docs says its applied to “all terms read during consulting” https://www.swi-prolog.org/pldoc/doc_for?object=term_expansion/2 Am I misreading it?

term_expansion/2 is only called on the toplevel term. If you want to perform transformations inside the term you need to do so yourself. An intermediate step is provided by goal_expansion/2, which is called for each goal term in a clause.

Also note that term_expansion/2 is called only once per term, i.e., only the first answer of the expansion is used. goal_expansion/2 is called on the goal until fixed point is reached.

2 Likes