[erlang-questions] tail recursion : sharing a learning and a question

Amit Murthy amit.murthy@REDACTED
Mon Aug 17 20:13:49 CEST 2009


Thanks Richard. A pretty neat solution and a very clear explanation.

  Amit

On Mon, Aug 17, 2009 at 10:12 PM, Richard Carlsson <richardc@REDACTED>wrote:

> Amit Murthy wrote:
>
>> I just learned that every iteration of the below code goes onto the stack.
>> The evaluation of the "catch" has something to do with it
>>
>> do_maintenance(CacheSz, HKIntvl, Oldest) ->
>>    try
>>        receive
>>            ...
>>        after HKIntvl ->
>>            ...
>>            do_maintenance(CacheSz, HKIntvl, NOldest)
>>        end
>>    catch
>>        error:Error ->
>>            ...
>>            do_maintenance(CacheSz, HKIntvl, Oldest)
>>    end.
>>
>> The right way of course is to not trap exceptions here, remove the
>> try-catch
>> and put the whole thing under a supervisor (with restart) behavior.
>> Which is what I have done now.
>>
>
> It would be sufficient to rewrite it like this:
>
>  do_maintenance(CacheSz, HKIntvl, Oldest) ->
>      try
>          receive
>              ...,
>              Oldest
>          after HKIntvl ->
>              ...,
>              NOldest
>          end
>      of
>        NewOldest -> do_maintenance(CacheSz, HKIntvl, NewOldest)
>      catch
>          error:Error ->
>              ...
>              do_maintenance(CacheSz, HKIntvl, Oldest)
>      end.
>
> The "protected" part of the code is the one between 'try' and 'of',
> or between 'try' and 'catch' if there is no 'of' section. In the
> protected part, tail recursive calls are not possible. (The call
> in the 'catch...end' section, however, is tail recursive here.)
>
> Basically, what your version of the code says is "if the recursive
> call fails, we must catch that before we are allowed to exit from
> the current call". The rewritten version above says "do the receive
> and the log_info or cleanup, and catch any errors in that part (but
> only in that part), then do a tail call to exit from the current call".
>
>  Would still like to know as to why the try-catch ends up killing tail
>> recursion. Can't the compiler catch this (pun intended) and optimize it
>> for
>> tail recursion?
>>
>
> No, because what the code says is that it should catch errors that may
> happen in the recursive call, and handle the errors using the context of
> the current call (e.g., the current value of Oldest). This means that
> the compiler must keep the stack entry for the current call until the
> recursive call has finished. Hence, no tail recursion optimization.
>
>    /Richard
>


More information about the erlang-questions mailing list