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

David Mercer dmercer@REDACTED
Mon Aug 17 18:25:59 CEST 2009


Amit wrote:
> 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?

Well, you *could* remove the try-catch and put that in a function that calls
do_maintenance/3, enabling the tail-call optimization, but that would change
the semantics of the function.  I believe the function, as written, would
need to keep the stack around (that is, not optimize the tail-call - which
isn't really a tail-call, since it is within the try-catch) unless you
decide to carry around an accumulator with the state that would have been in
the stack (specifically, a list of Oldest's).

That is, whatever mechanism you use to handle errors in the error-handler
would have to be handled in a tail-call-optimizable way.  I'm sure someone
else can explain it better than me, but I'm thinking of errors in the call
on the following line:

>             do_maintenance(CacheSz, HKIntvl, Oldest)

Your code, as written, handles that by pushing it up to the next exception
handler on the stack.  If you were to tail-call-optimize that stack frame
away, then the behavior of your program has changed.

Cheers,

David

> -----Original Message-----
> From: erlang-questions@REDACTED [mailto:erlang-questions@REDACTED] On
> Behalf Of Amit Murthy
> Sent: Sunday, August 16, 2009 8:15 AM
> To: Erlang
> Subject: [erlang-questions] tail recursion : sharing a learning and a
> question
> 
> Hi,
> 
> 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 though I could
> understand why.
> 
> 
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> %% Bad code, Bad code, Bad code, Bad code, Bad code, Bad code,
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> 
> do_maintenance(CacheSz, HKIntvl, Oldest) ->
>     try
>         receive
>             Message ->
>                 met_util:log_info(" pid -~p recieved unexpected
> message[~p].
> ",[self(), Message])
> 
>         after HKIntvl ->
>             NOldest = do_cleanup(CacheSz, Oldest, 100),
>             do_maintenance(CacheSz, HKIntvl, NOldest)
>         end
>     catch
>         error:Error ->
>             met_util:log("~p do_maintenance() caught exception ->
> ~p",[?MODULE, 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.
> 
> 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?
> 
> Regards,
>   Amit



More information about the erlang-questions mailing list