erlangs递归函数不仅仅是一个goto吗? [英] is erlangs recursive functions not just a goto?

查看:141
本文介绍了erlangs递归函数不仅仅是一个goto吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是为了把它直接在我的头上。考虑这个Erlang代码的例子:

  test() - > 
收到
{From,whatever} - >
%%做某事
test();
{From,somethingelse} - >
%%做别的东西
test();
结束。

不是test()调用,只是一个goto?



我问这个是因为在C中我们学到了,如果你做一个函数调用,返回位置总是放在堆栈上。我不能想象这里的Erlang必须是这样,因为这将导致一个stackoverflow。



在基本的。我们有两种不同的调用方式:
goto和gosub。
goto只是将程序流控制在别的地方,gosub记得你来自哪里,所以你可以返回。



给定这种思维方式,我可以看看erlang的递归更容易,因为如果我刚刚读取:test()作为一个goto,那根本就没有问题。



所以我的问题是:不是erlang只是使用一个goto而不是记住一个堆栈的返回地址?



编辑:



只是为了澄清我的观点:



我知道goto可以用一些语言来跳过这个地方。但是,只是suupose而不是做一些功能()你也可以做:goto someFunction()
在第一个例子中流程返回,在第二个例子中,流程继续在someFunction中,从不返回。



所以我们只需要跳转到方法起始点即可限制正常的GOTO行为。



如果你这样看, erlang递归函数调用看起来像一个goto。



(在我看来,goto是一个函数调用,无法返回你来自哪里)。这正是Erlang的例子。

解决方案

一个尾递归调用更多的是一个返回并立即调用另一个函数,而不是一个goto,执行。



解决您的最新问题:记录返回点只是在调用函数时执行的一点管理。返回点存储在堆栈帧中,其余部分必须分配和初始化(在正常调用中),包括局部变量和参数。使用尾递归,不需要分配一个新的帧,并且不需要存储返回点(以前的值正常工作),但需要执行其余的内务。



当函数返回时,还需要执行内务处理,其中包括丢弃本地和参数(作为堆栈帧的一部分)并返回到调用点。在尾递归调用期间,当前函数的当地人在调用新函数之前被丢弃,但不返回。



而不是像线程允许更轻量级的上下文切换与进程相比,尾部调用允许轻量级的函数调用,因为可以跳过一些内务管理。



goto& NAME 的声明更接近于您的想法,但不完全,因为它丢弃当地人。参数被保留在新调用的函数中。



还有一个简单的区别:尾部调用只能跳到一个函数入口点,而goto可以跳过任何地方(某些语言限制goto的目标,例如C,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.

In basic. 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 suupose 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.

解决方案

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

这篇关于erlangs递归函数不仅仅是一个goto吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆