今天继续学习函数的高级内容:
6. More about Functions
1)函数名是变量,可以赋值,传递,作为函数的返回值
如图:

2)匿名函数:
Lua允许匿名函数:如
f = function (x) return 2*x end -->创建了一个匿名函数,并将函数赋值给变量f
3)高级函数:
在Lua中,用其他函数的名称作为输入参数的函数,叫做高级函数。
作为输入参数的函数名,和一般的变量使用方式相同, 如:
或者:

4)闭包:
函数嵌套时:内部函数可以访问外部函数的变量,这个变量称作外部的局部变量:external local variable 或者 upvalue
如图所示:

i是Count的局部变量,在内嵌的匿名函数中被访问,每次递增一
注意:
(1)直接打印print(Cn()),打印的是内嵌函数的地址。
(2)c1 = Cn(),表示将Cn的内嵌函数付给了c1。和 c1 = Cn完全不同含义。
(3)c1只是Cn()内嵌函数的变量,但其中用到了Cn的局部变量i,则通过Lua的闭包机制,在c1中建立了一个i的实例。
(4)创建了两个Cn()的实例,c1和c2,他们拥有各自独立的外部局部变量i,他们的计数是相互独立的。
从技术上讲,闭包是值,而不是函数,有点类似于建立了一个类的实例,其中的upvalue都有自己的一个实例。
闭包技术可以作为一种沙箱实现,来创建安全的环境,把不安全代码放在一个闭包中,来限制访问的方式。
5)表的函数:
(1)对表,可以添加表对应的函数,如:
Lib = {}
Lib.foo = function (x,y) return x+y end
lib.goo = function (x,y) return x-y end
或者
Lib = {
foo = function (x,y) return x+y end,
goo = function (x,y) return x-y end
}
或者
Lib = {}
function Lib.foo(x,y) return x+y end
function Lib.goo(x,y) return x-y end
这种方式类似于C语言中给结构体加函数的方式。
6)局部函数:
将函数赋值给局部变量,可以限制函数的方位范围。如:
local f = function(x) return 2*x end 则,函数只能在f的作用域中使用。
或者,
local function f(x) return 2*x end 和上述的作用相同
对递归函数需要先声明局部函数,否则Lua会找不到相应的函数,如:
local fact
fact = function (n)
if n <= 0 then return 1
else return n*fact(n-1) end
end
7)尾调用(尾递归 Tail Calls)
function f()
return g()
end
当调用g()后不需要返回f(),则系统不需要保存f()的上下文,这种情况就称为尾调用。
这时,Lua不会再增加额外的栈来放置被调用的函数g(),在递归时能有效的防止栈溢出。
如:
function f(n)
if n > 0 then return f(n-1) end
end
这时不论n多大,Lua调用时都不会将f层层加栈。
可以讲尾调用当做一个goto语句,而不是一般的函数加栈调用方式。