I have a relatively complex use of answer subsumption (using subsumes/2
) for a transitive predicate whose base cases are defined by a dynamic predicate whose clauses are asserted through an abstract interpretation of a large-ish program (phew!).
Anyway, I need to backtrack through several answers to this tabled query, and for some reason it triggers an issue where I get an existence error for usermod:once/1
. I see that once
is defined away by metaprogramming, but evidently that metaprogramming isn't (always?) given a chance to work on the code generated in cp_opt.P
. So I changed the call to once/1
to (G,!)
and things work as I expected.
I think the "correct" fix would be to ensure that all the term expansions, etc apply to the code generated by cp_opt.P
in all cases, but this fixes the bad behavior at least.
Thanks! Your analysis is exactly right. However, I think your fix is not quite right. You changed
- findall(Leaf,('$$get_returns'(Cs,OSkel,Leaf),once(OpSpec2)),Leaves),
+ findall(Leaf,('$$get_returns'(Cs,OSkel,Leaf),(OpSpec2,!)),Leaves),
And the cut you added in the body of the findall has scope over that whole call of findall's second argument, i.e., it would cut away the alternatives in the $$get_returns call. This is fine if there is only one return, but not if there are more. So the better fix, I think, is:
+ findall(Leaf,('$$get_returns'(Cs,OSkel,Leaf),(OpSpec2->true;fail)),Leaves),
I will check this out and commit it, if it's OK.
Thanks again!
I had tried that first, but ran into a similar existence error (for ->). Would
(G,!;fail)
work?No, the scope of the ! is still too wide. The other thing to do is to go back to the once and import it later in that clause with:
ensure_imported(once/1,standard,SymTab),
That will put into the .xwam file an import of the once/1 predicate from where it's defined, and so then should be available to your code.
That did the trick; I reverted my change and then inserted
ensure_imported(once/1,standard,SymTab)
at line 244 ofcp_opt.P
.What I still don't understand is why the existence error only exhibited with a complex example like my whole application, rather than any of the simpler examples I tried to construct.
Excellent. Yeah, it's hard to remember when predicates are hard-coded and builtin or when they need to be imported. In this case, it is very low in the system so almost everything that is used needs to be explicitly imported. I definitely think of once/1 (and even more of ->/2) as always built-in, but they are not when they are "interpreted", as in the "call context" of the 2nd argument of the findall. Glad we finally tracked it down.
I, too, don't understand why/when those things show up. It may have to do with the other predicates being used in the file containing the answer-abstraction declaration. If those predicates are otherwise included (for some other reason), then there's no problem. All "standard" predicates are normally included automatically (unless it compiled in sysmod mode), so I would have thought that would have done it. But there must be other complications I'm not aware of.