• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

[Lua]尾调用消除(tail-callelimination)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

《Lua程序设计(第2版)》 6.3 正确的尾调用(proper tail call)

  Lua是支持尾调用消除(tail-call elimination)的,如下面对函数g的调用就是尾调用。

1 function f(x) return g(x) end

  尾调用之后,程序不需要保存任何关于函数f的栈(stack)信息,即不耗费任何栈空间。

  尾调用方法可用于编写状态机(state machine),类似于goto到另一个函数,如果没有尾调用消除,每次调用都会创建一个新的栈层(stack level),若干步之后有可能导致栈溢出。

  注意,以下几种情况均不是尾调用:

1 function f(x)
2     g(x)
3 end
4 
5 return g(x) + 1
6 return x or g(x)
7 return (g(x))

 

  举例,书中有个迷宫的例子,代码如下:

入口

room1

room2
room3

出口

room4

  

 1 function room1 ()
 2     local direction = io.read()
 3     if direction == "east" then
 4         room2()
 5     elseif direction == "south" then
 6         room3()
 7     else
 8         print("invalid direction!")
 9         room1()
10     end
11 end
12 
13 function room2 ()
14     local direction = io.read()
15     if direction == "west" then
16         return room1()
17     elseif direction == "south" then
18         return room4()
19     else
20         print("invalid direction!")
21         return room2()
22     end
23 end
24 
25 function room3 ()
26     local direction = io.read()
27     if direction == "north" then
28         return room1()
29     elseif direction == "east" then
30         return room4()
31     else
32         print("invalid direction!")
33         return room3()
34     end
35 
36 end
37 
38 function room4 ()
39     print("congratulations!")
40 end
41 
42 room1()

运行结果:

south
west
invalid direction!
east
congratulations!

 

我们写一个尾调用的简单循环:

 1 function room1()
 2     return room2()
 3 end
 4 
 5 function room2()
 6     print(111)
 7     return room1()
 8 end
 9 
10 room1()

运行结果:

111
111 -- 一直循环不会报错

 

不使用尾调用:

 1 function room1()
 2     room2()
 3 end
 4 
 5 function room2()
 6     print(111)
 7     room1()
 8 end
 9 
10 room1()

运行结果:

111
111 -- 循环几秒之后出现以下报错:

lua: stack overflow
stack traceback:
        [C]: in function 'print'
        6_propertailcall.lua:47: in function 'room2'
        6_propertailcall.lua:43: in function 'room1'
        6_propertailcall.lua:48: in function 'room2'
        6_propertailcall.lua:43: in function 'room1'
        6_propertailcall.lua:48: in function 'room2'
        6_propertailcall.lua:43: in function 'room1'
        6_propertailcall.lua:48: in function 'room2'
        6_propertailcall.lua:43: in function 'room1'
        6_propertailcall.lua:48: in function 'room2'
        ...
        6_propertailcall.lua:48: in function 'room2'
        6_propertailcall.lua:43: in function 'room1'
        6_propertailcall.lua:48: in function 'room2'
        6_propertailcall.lua:43: in function 'room1'
        6_propertailcall.lua:48: in function 'room2'
        6_propertailcall.lua:43: in function 'room1'
        6_propertailcall.lua:48: in function 'room2'
        6_propertailcall.lua:43: in function 'room1'
        6_propertailcall.lua:51: in main chunk
        [C]: ?

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
lua垃圾回收机制发布时间:2022-07-22
下一篇:
Redis入门(6)-Lua脚本发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap