Erlang 的递归函数不只是一个 goto 吗? [英] Is Erlang's recursive functions not just a goto?

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

问题描述

只是想把它放在我的脑海里.考虑这个 Erlang 代码示例:

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.

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

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

我问这个是因为在 C 中我们学到了,如果你做一个函数调用,返回位置总是放在堆栈上.我无法想象这一定是 Erlang 的情况,因为这会导致计算器溢出.

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.

我们有两种不同的函数调用方式:goto 和 gosub.goto 只是将程序流程引导到其他地方,gosub 会记住您来自哪里,以便您可以返回.

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.

按照这种思路,我可以更轻松地查看 Erlang 的递归,因为如果我只是将:test() 作为 goto 阅读,那么完全没有问题.

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.

因此我的问题是:不是 :Erlang 只是使用 goto 而不是记住堆栈上的返回地址吗?

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

只是为了澄清我的观点:

Just to clarify my point:

我知道某些语言中可以使用 goto 来跳转到所有地方.但只是假设而不是做 someFunction() 你也可以这样做: goto someFunction()在第一个示例中,流程返回,在第二个示例中,流程仅在 someFunction 中继续并且永不返回.

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.

因此,我们只能通过跳转到方法起点来限制正常的 GOTO 行为.

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

如果你这样看,那么 Erlang 递归函数调用看起来就像一个 goto.

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

(在我看来,goto 是一个无法返回您来自何处的函数调用).这正是 Erlang 示例中发生的事情.

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

推荐答案

尾递归调用更像是返回并立即调用另一个函数",而不是 goto,因为要执行内务处理.

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.

goto &NAME" 声明在Perl 更接近您的想法,但不完全是,因为它丢弃了本地人.为新调用的函数保留参数.

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.

还有一个简单的区别:尾调用只能跳到函数入口点,而goto最多可以跳到任何地方(有些语言限制goto的目标,比如C,goto不能跳到函数外函数).

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

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

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