Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Erlang's recursive functions not just a goto?

Just to get it straight in my head. Consider this example bit of Erlang code:

 test() ->
      receive
          {From, whatever} ->
                %% do something
               test();
          {From, somethingelse} ->
               %% do something else
               test();
 end.

Isn't the test() call, just a goto?

I ask this because in C we learned, if you do a function call, the return location is always put on the stack. I can't imagine this must be the case in Erlang here since this would result in a stackoverflow.

We had 2 different ways of calling functions: goto and gosub. goto just steered the program flow somewhere else, and gosub remembered where you came from so you could return.

Given this way of thinking, I can look at Erlang's recursion easier, since if I just read: test() as a goto, then there is no problem at all.

hence my question: isn't :Erlang just using a goto instead of remembering the return address on a stack?

EDIT:

Just to clarify my point:

I know goto's can be used in some languages to jump all over the place. But just supose instead of doing someFunction() you can also do: goto someFunction() in the first example the flow returns, in the second example the flow just continues in someFunction and never returns.

So we limit the normal GOTO behaviour by just being able to jump to method starting points.

If you see it like this, than the Erlang recursive function call looks like a goto.

(a goto in my opinion is a function call without the ability to return where you came from). Which is exactly what is happening in the Erlang example.

like image 822
Toad Avatar asked Sep 27 '09 11:09

Toad


1 Answers

A tail recursive call is more of a "return and immediately call this other function" than a goto because of the housekeeping that's performed.

Addressing your newest points: recording the return point is just one bit of housekeeping that's performed when a function is called. The return point is stored in the stack frame, the rest of which must be allocated and initialized (in a normal call), including the local variables and parameters. With tail recursion, a new frame doesn't need to be allocated and the return point doesn't need to be stored (the previous value works fine), but the rest of the housekeeping needs to be performed.

There's also housekeeping that needs to be performed when a function returns, which includes discarding locals and parameters (as part of the stack frame) and returning to the call point. During tail recursive call, the locals for the current function are discarded before invoking the new function, but no return happens.

Rather like how threads allow for lighter-weight context switching than processes, tail calls allow for lighter-weight function invocation, since some of the housekeeping can be skipped.

The "goto &NAME" statement in Perl is closer to what you're thinking of, but not quite, as it discards locals. Parameters are kept around for the newly invoked function.

One more, simple difference: a tail call can only jump to a function entry point, while a goto can jump most anywhere (some languages restrict the target of a goto, such as C, where goto can't jump outside a function).

like image 138
outis Avatar answered Oct 29 '22 00:10

outis