Lua之函数
在Lua中,函数是一种“第一类值(first-class value)”,具有特定的词法域。
“第一类值”是什么意思呢? 这表示在Lua中,函数和和其他传统类型的值具有相同的权利,函数可以存储在变量中或table中,可以作为实参传递给其他函数,还可以作为其他函数的返回值。
“词法域”是什么意思呢?这是指一个函数可以嵌套在另一个函数中,嵌套函数可以访问外部函数的变量。
“第一类值”和“词法域”是Lua函数中极为重要的两个概念,一定要牢记在心心心!!!
1.lua函数是什么
在Lua中,函数与其他值一样都是匿名的,即它们都没有名称,当讨论一个函数名时,实际是在讨论一个持有某函数的变量。了解这一点很重要,因为我们可以通过匿名函数实现泛型编程,比如table.sort函数的应用例子:
network={
{name = "paul",IP="10.17.161.30"},
{name = "kate",IP="10.17.161.31"},
{name = "lua",IP="10.17.161.32"},
};
如果想以name字段,按照反向的字符顺序来排序这个table的话,只需要这么写:
table.sort(network,function(a,b) return (a.name > b.name) end);
2.Lua的闭合函数(闭包)
先看一个例子:
function newCounter()
local i = 0
return function() -- anonymous function
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) --> 1
print(c1()) --> 2
调用newCounter()实际上就是返回了匿名函数的一个引用,而与匿名函数相关的变量i称之为非局部的变量,也称为upvalue。上述的情况就是Lua中的closure概念,简单来讲,一个closure就是一个函数加上该函数所需访问的所有“非局部的变量”。如果再次调用newCounter,那么它会创建一个新的局部变量i,从而也将得到一个新的closure:
c2 = newCounter()
print(c2()) --> 1
print(c1()) --> 3
print(c2()) --> 2
因此,c1和c2是同一个函数所创建的两个不同的closure,它们各自拥有局部变量i的独立实例。技术角度来讲,Lua中只有closure,而没有函数,因为函数只是一种特殊的closure,我们谓之为函数的closure,实际是那种没有访问非局部变量的closure。
向更深入了解闭包,请参考http://www.voidcn.com/article/p-nuxbrpko-bks.html
3.尾调用
所谓“尾调用”,就是一种类似goto语句的函数调用。尾调用不会耗费栈空间,因此,在程序中可以可以拥有无数嵌套的尾调用,但是务必确保当前调用是一条“尾调用”,判断的准则其实很简单,那就是当前调用是原子操作。
例子:
function f(x) g(x) end --需要丢弃g返回的临时结果
return g(x)+1 --还需要做一次加法运算
return x or g(x) --必须调整为一个返回值
return (g(x)) --必须调整为一个返回值
return x[i].foo(x[j] + a*b,i + j) --满足