正确的尾调用

简介: 正确的尾调用

Lua 语言中有关函数的另一个有趣的特性是: Lua 语言是支持尾调用消除的。这意味着 Lua 语言可以正确地尾递归,虽然尾调用消除的概念并没有直接涉及递归。


尾调用tail call )是被当做函数调用使用的跳转。当一个函数的最后一个动作是调用另一个函数而没有再进行其他工作时,就形成了尾调用。例如,下列代码中对函数 g 的调用就是尾调用:

function f(x) x = x +1; return g(x) end


当函数 f 调用完函数 g 之后, f 不再需要进行其他的工作。这样,当被调用的函数执行结束后,程序就不再需要返回最初的调用者。因此,在尾调用之后,程序也就不需要在调用栈中保存有关调用函数的任何信息。当 g 返回时,程序的执行路径会直接返回到调用 f 的位置。在一些语言的实现中,例如 Lua 语言解释器,就利用了这个特点,使得在进行尾调用时不使用任何额外的栈空间。我们就将这种实现称为尾调用消除(tail-call elimination)。


由于尾调用不会使用栈空间,所以一个程序中能够嵌套的尾调用的数量是无限的。例如,下列函数支持任意的数字作为参数:

function foo(n)
  if n > 0 then return foo(n -1) end
end


该函数永远不会发生栈溢出。


关于尾调用消除的一个重点就是如何判断一个调用是尾调用。很多函数调用之所以不是尾调用,是由于这些函数在调用之后还进行了其他工作。例如,下例中调用 g 就不是尾调用:

function f(x) g(x) end


这个示例的问题在于,当调用完 g 后,f在返回前还不得不丢弃 g 返回的所有结果。类似的,以下的所有调用也都不符合尾调用的定义:

return g(x) + 1     -- 必须进行加法
return x or g(x)    -- 必须把返回值限制为1个
return (g(x))       -- 必须把返回值限制为1个


Lua 语言中,只有形如 return func(args) 的调用才是尾调用。不过,由于 Lua 语言会在调用前对 func 及其参数求值,所以 func 及其参数都可以是复杂的表达式。例如,下面的例子就是尾调用:

return x[i].foo(x[j] + a*b, i+j)
目录
相关文章
尾调用和尾调用递归
尾调用和尾调用递归是程序设计中的重要概念,前者指函数执行的最后一操作为函数调用,后者利用此特性实现递归,二者均能优化性能、提高代码可读性,避免栈溢出,但适用范围有限且理解难度较高。【10月更文挑战第11天】
|
1月前
|
机器学习/深度学习 人工智能 算法
尾调用递归的常见应用场景有哪些?
【10月更文挑战第11天】 尾调用递归在程序设计中广泛应用,包括数学计算(如斐波那契数列、组合数)、数据结构遍历(如树、链表)、分治法(如归并排序、快速排序)、动态规划、表达式求值、游戏开发、人工智能与机器学习等领域。通过递归地处理子问题,尾调用递归能够提高代码的可读性和效率,同时避免栈溢出等问题。然而,需根据具体问题合理选择使用。
|
5月前
|
算法
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
49 0
|
6月前
|
存储 算法 编译器
顺序表的实现(头插、尾插、头删、尾删、查找、删除、插入)
顺序表的实现(头插、尾插、头删、尾删、查找、删除、插入)
|
4月前
|
存储
头指针和头结点的区别
头指针和头结点的区别
166 1
|
5月前
|
算法
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
62 0
|
5月前
|
算法
数据结构和算法学习记录——线性表之双向链表(下)-头插函数、头删函数、查找函数、pos位置之前插入结点、pos位置删除结点及其复用、销毁链表函数
数据结构和算法学习记录——线性表之双向链表(下)-头插函数、头删函数、查找函数、pos位置之前插入结点、pos位置删除结点及其复用、销毁链表函数
30 0
|
6月前
链表的几种常见方法
链表的几种常见方法
27 1
|
6月前
(数据结构)单链表 —— 尾插,尾删,头插,头删,查找,插入,删除。
数据结构单链表 —— 尾插,尾删,头插,头删,查找,插入,删除
40 0
|
6月前
|
存储
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)