scryer-prolog icon indicating copy to clipboard operation
scryer-prolog copied to clipboard

asserta/1: no 7.6.2 term-to-body conversion

Open UWN opened this issue 11 months ago • 5 comments

?- asserta((f(X) :- X,X)).
   true.
?- clause(f(X),Body).
   Body = (X,X), unexpected.
   Body = (call(X),call(X)). % expected, but not found

UWN avatar Feb 03 '25 19:02 UWN

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!)

rotu avatar May 20 '25 04:05 rotu

SICStus:

| ?- asserta((f(X) :- X,X)).
yes
| ?- clause(f(X),Body).
Body = (call(X),call(X)) ? ;
no

UWN avatar May 20 '25 04:05 UWN

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

rotu avatar May 20 '25 07:05 rotu

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.

UWN avatar May 20 '25 07:05 UWN

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)).

rotu avatar May 20 '25 15:05 rotu