Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Language agnostic 什么是尾部递归消除?_Language Agnostic_Recursion_Tail Recursion_Tail Call Optimization_Program Transformation - Fatal编程技术网

Language agnostic 什么是尾部递归消除?

Language agnostic 什么是尾部递归消除?,language-agnostic,recursion,tail-recursion,tail-call-optimization,program-transformation,Language Agnostic,Recursion,Tail Recursion,Tail Call Optimization,Program Transformation,史蒂夫·耶格在一封信中提到了这一点,我不知道这是什么意思,有人能告诉我吗 它与以下内容相同吗?来源: “…尾部递归消除是一个 尾部呼叫消除的特殊情况 其中tail调用是对 函数本身。在这种情况下 呼叫可以由跳转到 移动后启动该功能 新的论据,以适当的方式 寄存器或堆栈位置…” 发件人: “…调用函数时,计算机必须”记住“调用它的位置,返回地址,以便在调用完成后返回到该位置并显示结果。通常,这些信息保存在堆栈上,这是一个返回位置的简单列表,按到达它们所描述的调用位置的时间顺序排列。有时,函数在完成

史蒂夫·耶格在一封信中提到了这一点,我不知道这是什么意思,有人能告诉我吗

它与以下内容相同吗?

来源:

“…尾部递归消除是一个 尾部呼叫消除的特殊情况 其中tail调用是对 函数本身。在这种情况下 呼叫可以由跳转到 移动后启动该功能 新的论据,以适当的方式 寄存器或堆栈位置…”

发件人:

“…调用函数时,计算机必须”记住“调用它的位置,返回地址,以便在调用完成后返回到该位置并显示结果。通常,这些信息保存在堆栈上,这是一个返回位置的简单列表,按到达它们所描述的调用位置的时间顺序排列。有时,函数在完成所有其他操作后所做的最后一件事就是简单地调用函数(可能是函数本身),并返回其结果。使用尾部递归,不需要记住调用的位置-相反,我们可以不使用堆栈,新调用的函数将直接将其结果返回给原始调用方在这种情况下,将调用转换为分支或跳转称为尾部调用优化。请注意,尾部调用不必在源代码中所有其他语句之后出现;必须立即返回其结果,因为如果执行优化,调用函数在调用后将永远没有机会执行任何操作……”


尾部调用消除是一种节省堆栈空间的优化。它将函数调用替换为转到。尾部递归消除是一样的,但增加了函数调用自身的约束

基本上,如果函数
a
做的最后一件事是
返回a(params…
,则可以消除堆栈帧的分配,而是设置适当的寄存器并直接跳转到函数体中

考虑一个(虚构的)调用约定,它传递堆栈上的所有参数并返回某个寄存器中的值

某些函数可以编译为(在想象的汇编语言中):

不管上面的实际操作是什么,每次调用函数都会占用一个全新的堆栈框架。然而,由于在尾部调用函数之后除了返回之外什么都不会发生,我们可以安全地优化这种情况

导致:

function:
//Reading params B, C, & D off the stack (but only on the first call)
pop B
pop C
pop D
function_tail_optimized:
//Do something meaningful, including a base case return
...
//Instead of a new stack frame, load the new values directly into the registers
load B, B*
load C, C*
load D, D*
//Don't call, instead jump directly back into the function
jump function_tail_optimized
最终结果是一个等价函数,它可以节省大量堆栈空间,特别是对于导致大量递归调用的输入


我的回答需要很多想象力,但我认为你可以理解。

那么这与尾部调用优化是同一回事吗?是的,只是增加了一个约束,即调用是对它发起的函数的。很抱歉,这不是很清楚。
function:
//Reading params B, C, & D off the stack (but only on the first call)
pop B
pop C
pop D
function_tail_optimized:
//Do something meaningful, including a base case return
...
//Instead of a new stack frame, load the new values directly into the registers
load B, B*
load C, C*
load D, D*
//Don't call, instead jump directly back into the function
jump function_tail_optimized