Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

meta_predicate/1 directive is sometimes not applied #2625

Open
triska opened this issue Oct 18, 2024 · 9 comments
Open

meta_predicate/1 directive is sometimes not applied #2625

triska opened this issue Oct 18, 2024 · 9 comments

Comments

@triska
Copy link
Contributor

triska commented Oct 18, 2024

I am filing the short example from #2624 (comment) here as a simpler issue. With:

:- meta_predicate(p(0)).

p(t).

We get:

?- p(X).
   X = t, unexpected.
   false. % expected

Reason: The call is expected to be user:X, and thus not unifiable with t.

@hurufu
Copy link
Contributor

hurufu commented Oct 18, 2024

Meta-predicate argument expansion is applied only per goal, and not on a term level – this is the root of a problem. You can check it for example by adding the following to your snippet:

:- dynamic(t/0).
t :- p(t).

And then doing following query.

?- listing(t/0).
t :-
   p(user:t).
   true.

@triska
Copy link
Contributor Author

triska commented Oct 18, 2024

@hurufu: What you posted does not correspond to the example in the issue, please try it with:

t :- p(_).

@hurufu
Copy link
Contributor

hurufu commented Oct 18, 2024

Ah yes, but it is still quite hard to solve with current loader in a systematic way and without pilling-up workarounds on top of workarounds.

I think I can do a warning in this case, as was suggested recently.

@hurufu
Copy link
Contributor

hurufu commented Oct 18, 2024

Interestingly enough the following code:

t :- p(_).

Already triggers a warning:

% Warning: Meta-predicate detected, but no qualified variables found at line 29 of warnings.pl

This happens because p/1 calls an unbound variable that doesn't appear in the head of the clause.

@hurufu
Copy link
Contributor

hurufu commented Oct 18, 2024

Actually I've tested this situation a little bit more, and I think the problem is more subtle. The following code behaves as expected:

:- module(m, [p/0]).

:- meta_predicate(b(:)).
b(t).

p :- b(X).

Query:

?- p.
   false.

@hurufu
Copy link
Contributor

hurufu commented Oct 18, 2024

Because there is no distinction between t and user:t I'm even starting to think that behavior is correct...

@hurufu
Copy link
Contributor

hurufu commented Oct 18, 2024

By "no distinction" I mean that call(t) is the same as call(user:t) if executed in the user context, which is the case for this bug.

@hurufu
Copy link
Contributor

hurufu commented Oct 18, 2024

I have found a workaround:

:- meta_predicate(q(0,-)).
q(A,A).

p(A) :- q(t, A).

Now it works as expected:

?- p(A).
   A = user:t.

Because module qualifier are added in the place of call, this means that for original example, there was no enough information whether to add or not those qualifiers.

@hurufu
Copy link
Contributor

hurufu commented Oct 19, 2024

I've actually have spent some time trying to write a warning, but I'm kinda stuck. Consider the following code:

:- meta_predicate(g(0,-)).
g(A,A).

:- meta_predicate(p(0)).
p(A) :- g(t, A).
p(A) :- A = t.
p(t).

o :- p(A), portray_clause(A).

First clause of p/1 is correct and shouldn't trigger a warning, but other two clauses should trigger it, and I don't know how to distinguish between them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants