asserta/1: no 7.6.2 term-to-body conversion
?- asserta((f(X) :- X,X)).
true.
?- clause(f(X),Body).
Body = (X,X), unexpected.
Body = (call(X),call(X)). % expected, but not found
Also note ISO/IEC 13211-2 7.4.1.1, 6.5.2.2.
~~If asserta/1 is executed in the calling context of module M, then the body would (I think) be (M:call(X), M:call(X)), so usually (user:call(X), user:call(X)).~~ EDIT: I thought wrong.
I think it is important to capture and bind the calling context here, and not when the dynamic procedure is executed (otherwise every procedure becomes context sensitive by default!)
SICStus:
| ?- asserta((f(X) :- X,X)).
yes
| ?- clause(f(X),Body).
Body = (call(X),call(X)) ? ;
no
SICStus:
| ?- asserta((f(X) :- X,X)). yes | ?- clause(f(X),Body). Body = (call(X),call(X)) ? ; no
I don’t know if it makes a real difference whether we do module-aware term-to-body conversion so long as the effect of calling it is the same.
I also don’t know how closely to hew to SICStus. (I know you have opinions about strict parsing!)
There are some other interesting cases here that can stress-test our expansion:
:- module(a, []).
:- dynamic m:a/1.
b(1).
m:c([]).
m:d([H|T]) :- q(H), r(T).
m:(e(X) :- s(X), t(X)).
f(X) :- m:(u(X), v(X)).
https://sicstus.sics.se/sicstus/docs/4.0.3/html/sicstus/ref_002dmod_002dmpc.html#ref_002dmod_002dmpc
SICStus, Trealla, ECLiPSe, Tau, SWI, X, IF all agree (and have modules). GNU, XSB, IV agree too (no modules/different modules). Scryer, Ichiban, YAP, B, Minerva don't do the conversion. Ciao has already a different functor for (',')/2.
It looks like I misread and that regular goal expansion is supposed to apply when the body is unqualified.
I think I wrongly extrapolated from the first example in ISO/IEC 13211-2 6.5.3. Example as written:
defining module = m, context module = foo.
...
foo:asserta(m:bar(X) :- baz(X)).
...
bar(X) :- foo:baz(X).
SICStus:
| ?- foo:asserta((m:bar(X) :- baz(X))), m:clause(bar(X),B).
B = baz(X)
SWI:
?- foo:asserta((m:bar(X) :- baz(X))), m:clause(bar(X),B).
B = foo:baz(X).
In the case of a module-qualified body, SICStus and SWI also disagree. SICStus:
| ?- asserta((f(X) :- m:(X,X))),
clause(f(X),B).
B = m:(call(X),call(X))
SWI:
?- asserta((f(X) :- m:(X,X))),
clause(f(X),B).
B = (call(m:X), call(m:X)).