[m-users.] Ambiguous tail recursion?

Julien Fischer jfischer at opturion.com
Wed Jul 17 12:14:10 AEST 2019


Hi,

On Tue, 16 Jul 2019, Julian Fondren wrote:

> Consider this module:
>
>   :- module tailornot.
>   :- interface.
>   :- import_module io.
>   :- pred main(io::di, io::uo) is det.
>   :- implementation.
>   :- import_module list, bool, int.
>
>   main(!IO) :-
>       X = (test([1, 2, 3]) -> yes; no),
>       io.print(X, !IO), io.nl(!IO).
>
>   :- pred test(list(int)::in) is semidet.
>   test([]).
>   test([X | Xs]) :-
>       X < 5,
>       test(Xs).
>
> Is it defined that test/1 is tail recursive?

It depends how you are compiling it.  If you're using a hlc grade
and invoke the compiler with --no-optimize-tailcalls, then definitely
not!

Assuming you're not doing something like that then yes, the above
will be compiled into tail recursive code; if you want to make sure
then ask the compiler, e.g. invoke it with --warn-non-tail-recursion=self.

(We also have pragma versions of that warning, although they are
currently undocumented.  If you put

     :- pragma require_tail_recursion(test/1, [error]).

in your program, then the compiler will emit an error if test/1
is not going to compiled in a way that is tail recursive.)

> 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.

Julien.


More information about the users mailing list