[m-rev.] Section for the Languge Reference Manual

Mark Brown mark at mercurylang.org
Thu Oct 13 01:52:53 AEDT 2022


On Wed, Oct 12, 2022 at 11:25 PM Volker Wysk <post at volker-wysk.de> wrote:
>
> Hi!
>
> I've summarized what I've learned about optimization that deletes predicate
> calls, which may throw an exception. See the recent thread "Existential
> higher-order type" in mercury-users.
>
> You might want to include it (or an edited version of it) in the Language
> Reference Manual, as a section of the Exception Handling chapter.

Thanks Volker! I was also thinking about how to clarify the reference
manual. I agree with the content of your first three paragraphs,
except that there are some other effects aside from exceptions, such
as trace goals (the user most likely wants trace goals to be removed,
so they can see where the optimization has been applied). Also I was
going to put the information in a couple of existing places that
mention this topic, rather than in exception handling.

>
> In the fourth paragraph ("So what...") I've written my thoughts about what
> to do. You might want to skip or rewrite it.

I don't agree with adding this, in fact I think we should caution
against using the style. Consider the following code:

shoot(Target, !IO) :-
    valid_target(Target),
    unsafe_shoot(Target, !IO).

The problem is that nothing in the declarative semantics says the
check must come before the unsafe call, when clearly the intent is not
to shoot first and ask questions later. (I'm guessing this doesn't
apply to your case from the earlier thread, but I think others are
likely to try to write code in this way.)

You can tell the compiler not to re-order conjunctions, but that isn't
enough - you also have to tell anyone modifying the code that they
can't reorder conjunctions either, at least not without considering
the operational semantics first.

A typical way of writing code that behaves as the above is intended to is:

shoot(Target0, !IO) :-
    valid_target(Target0, Target),
    unsafe_shoot(Target, !IO).

This has a much clearer reading: Target0 is a possibly unsafe target,
but Target is definitely safe. In addition, the mode system will
ensure they are executed in the right order.

I'll post a diff for the reference manual sometime soon.

Cheers,
Mark

>
> The desired effect might also be achieved with impurity. I don't have a
> paragraph about it, since I'm not sure about it.
>
> Here it is:
>
> ----------------------------------------------
> Some goals are equivalent to true and don't have any "visible" results. This
> means they don't contribute to the computation. But they still may
> contribute by throwing exceptions. For instance, an invocation of a
> deterministic predicate, which doesn't have any output arguments, can still
> throw an exception.
>
> In some cases, such a goal will be optimized away, and its exceptions won't
> be thrown. It depends on the optimization level and the chosen language
> semantics if this will happen.
>
> The default is the strict commutative semantics. Here such goals will only
> get optimized away, when Mercury can derive that the goal always terminates
> and doesn't throw an exception. There are other semantics, see chapter "14
> Semantics" in the Language Reference Manual. For instance, when specifying
> the --no-fully-strict argument to the compiler, it is allowed to optimize
> away such goals. See the chapter "9.6 Language semantics options" in the
> User Guide. When the compiler is allowed to do so, then it will, in most
> optimization levels.
>
> So what if you want to throw exceptions, in goals (such as predicate or
> function calls) that otherwise don't have any effect on the computation? You
> might want to have a predicate with no output, which checks its input and
> throws an exception if it is invalid. And you want to use a semantics, which
> allows for optimizing the call away, or you want to be independent of the
> used semantics. Then you will have to do it differently. Return an error as
> an output argument (use maybe/1) and let the caller throw the exception. If
> the caller itself can be optimized away, then let it do the same - return an
> error in an output argument, and so on. Until you reach code that
> contributes (non-exception wise) to the main computation.
>
> ... can it also be done with impurity? ...
> ----------------------------------------------
>
>
> Happy hacking,
> Volker
> _______________________________________________
> reviews mailing list
> reviews at lists.mercurylang.org
> https://lists.mercurylang.org/listinfo/reviews


More information about the reviews mailing list