[m-dev.] pragmas should specify pred/func as well as name and arity

Zoltan Somogyi zoltan.somogyi at runbox.com
Thu Apr 29 14:54:30 AEST 2021



On Thu, 29 Apr 2021 14:33:34 +1000, Peter Wang <novalazy at gmail.com> wrote:
> > However, for pragmas that assert something, such as promise_pure,
> > applying them to both a predicate and a function when the programmer
> > intended applying them to only one is a more significant problem.
> > I believe we should update the pragmas that use the first syntax
> > to first allow, and eventually require, the programmer to say whether
> > they mean pred foo/2 or func foo/2.
> 
> Can we require something more specific than name/arity if there is
> actual ambiguity?

I presume you mean "ONLY when there is an ambiguity".

My answer would be "no". Just because there is no ambiguity now
does not mean there won't be later. If e.g. a pragma says foo/2,
and the only foo/2 is currently a predicate, then the meaning of the
pragma should not change to apply to func foo/2 as well, when
it is added later. Having a pragma written now apply to code
written in the future would be ... surprising.

> I already dislike having to specify the arity when
> there is only one such thing by that name.

You may think there is only one predicate baz, but (a) you may be wrong,
and (b) even if you are right right now, you may become wrong later.
Code written by Fergus and Tom had lots of predicate names that existed
with more than one arity, until I systematically eliminated most such
ambiguities, leaving mostly just the intentional ones, such as set.init. 
(To help with that process, I even added a command to mdb
to find those ambiguities.)
 
> > I can see three broad approaches to how this could be done.
> > 
> > Approach 1 would be to wrap the name/arity pair in either pred() or func().
> > This would look good, but unfortunately the second syntax also uses terms
> > whose top function symbol is either pred or func, and there are some pragmas
> > that allow the subject that they apply to to be specified using either the first
> > or the second syntax (see attached table), so this would probably serve
> > as a source of confusion. And the compiler's error messages, having to
> > describe two possible ways to fix any syntax errors (one to reach each kind
> > of valid syntax), couldn't help as much as we would like them to.
> 
> This seems ideal to me. I don't really understand the problem with error
> messages. If the compiler cannot parse the term, I think the compiler
> can just say something like:
> 
>     The argument must have one of these forms:
> 
>         NAME/ARITY
>         pred(NAME/ARITY)
>         func(NAME/ARITY)
>         NAME(MODES)
> 
> and the user should get the idea.

Actually, there is one more, NAME(MODES) = MODE, for functions,
and the first one is one I would prefer not to advertise. (Existing pragmas,
but definition, should not get any error messages.)

But yes, your approach should solve the error message problem.

> > Approach 2 would be to add a "_pred" or "_func" suffix to the pragma name,
> > such as ":- pragma inline_func(foo/2).". We have already used this approach
> > when replacing ":- external(foo/2)." with ":- external_{pred,func}(foo/2).".
> > However, there are some pragmas, such as "terminates", for which neither
> > that suffix, nor a similar prefix, would look all that natural.
> 
> I don't especially like it.

I don't especially like any of the approaches, but I want *something* that
resolves the fundamental pred vs func ambiguity.

> > Approach 3 would be to add an extra  argument, containing simply either
> > "pred" or "func", to the pragma's argument list, just before the argument
> > that now contains just foo/2.
> 
> If the argument was optional then I could ignore it :)

It eventually wouldn't be, so ignoring it would work only in the short term :-(

> pragma promise_pure is not redundant because this is correct:
> 
>     :- pred foo(io::di, io::uo) is det.
>     :- pragma promise_pure(foo/2).
> 
>     foo(!IO) :-
>         impure do_foo.
> 
> but this is wrong:
> 
>     foo(!IO) :-
>         promise_pure (
>             impure do_foo
>         ).

You are right.

Zoltan.


More information about the developers mailing list