[m-users.] Ambiguous tail recursion?

Julien Fischer jfischer at opturion.com
Wed Jul 17 13:04:30 AEST 2019


On Tue, 16 Jul 2019, Julian Fondren wrote:

> On 2019-07-16 21:14, Julien Fischer wrote:

> OK, cool.
>
>>>  It seems to be just as valid for it to walk to the end of the list,
>>>  hit the [], and then walk backwards to test 3 < 5, 2 < 5, 1 < 5.
>>
>>  It would be valid, but there's no reason for the compiler to re-arrange
>>  the code that way.
>
> OK, but what if the code is instead
>
>    test([X | Xs]) :-
>        test(Xs),
>        X < 5.
>
> Normally I read Mercury code as if conjunction order doesn't matter at
> all, but if it does matter to tail recursive code (without semantics
> flags to disable reordering), then I still have to think about order
> to an extent.

The order of conjunctions doesn't matter to the declarative semantics of
the code; it definitely matters to the operational ones.   And with the
above example, what's going to happen is again dependent on what
optimization are enabled.  Enabling --constraint-propagation, which
moves semidet goals to as early as possible, will cause the compiler to
re-order the conjunction in the above predicate (and as a result of that
it will be become tail recursive.)

Note that how much the compiler is allowed to reorder your code is
controlled by which semantics are selected -- see the ``Semantics''
chapter of the reference manual.  By default, the compiler is allowed to
reorder both conjunctions and disjunctions for optimization purposes
(beyond whatever reordering is required for mode correctness).

> At least I should have a style rule like "put tail calls at the end".

As a rule of thumb, sure.  The rationale for the addition of the tail
recursion warnings and pragmas was to give programmers a mechansim for
stating that tail recursion *must* occur.

Julien.


More information about the users mailing list