先说个容易犯的错误。
下面这种写法是错误的。
1 2 3 4 5
| local fact = function (n) if n == 0 then return 1 else return n*fact(n-1) end end
|
错误就在于,Lua编译到fact(n-1)时,局部的fact尚未定义完,此时调用的是全局的fact。改正的写法如下:
1 2 3 4 5 6
| local fact fact = function (n) if n == 0 then return 1 else return n*fact(n-1) end end
|
这还有个术语,叫前向声明(forward declaration)。
下面我们来看看尾调用。都知道尾调用不会耗费栈空间,所以一个程序可以拥有无数嵌套的尾调用。例如,调用下面的函数时,传入任何数字作为参数都不会造成栈溢出:
1 2 3
| function foo (n) if n > 0 then return foo(n - 1) end end
|
不过要仔细甄别是否是尾调用。标准就是看函数在调用之后是不是什么也不做。下面举几个反例,都不是尾调用:
1 2 3
| return g(x) + 1 return x or g(x) return (g(x))
|
一般来说,必须要符合“return ()”的形式。
1
| return x[i].foo(x[j] + a*b, i + j)
|
尾调用的一大应用就是编写状态机。比如常见的迷宫游戏的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| function room1 () local move = io.read() if move == "south" then return room3() elseif move == "east" then return room2() else print("invalid move") return room1() end end function room2 () local move = io.read() if move == "south" then return room4() elseif move == "west" then return room1() else print("invalid move") return room2() end end function room3 () local move = io.read() if move == "north" then return room1() elseif move == "east" then return room4() else print("invalid move") return room3() end end function room4 () print("congratulations!") end
|