1:lua函数是匿名的
lua函数和其它lua值一样,都是匿名的,即它们本身没有名称。当讨论一个函数(如print)时,实际上是讨论一个持有某函数的变量。这于一个变量持有其它lua值是一个道理。如
function foo(x) return 2*x end 与 foo=function(x) return 2*x end 是等价关系。
再如:table.sort函数参数第二个参数就需要一个匿名函数参数
network = { {name = "grauna",IP="210.26.30.34"}, {name="arraial",IP="210.26.30.23"}, {name ="lua",IP="210.26.23.12"}, {name = "derain",IP="210.26.23.20"}, } table.sort(network,function(a,b) return (a.name>b.name) end)
像table.sort这类接收一个匿名函数作为实参的函数属于高阶函数。
正是lua函数是匿名的原因,当讨论一个函数(如print)时,实际上是讨论一个持有某函数的变量。所以lua函数可以存储在全局变量或者局部变量中。
比如table.sort函数就是一个局部函数。再如package模块里的某些函数,也只是在该package里可见。
2:形参的使用与C函数的形参使用有点区别;在lua中可以修改形参的值,如下
function func(n)
n = n or 1
count = count + n
end
3:lua函数支持多重返回值,lua程序设计第二版53页有一句话:只有当一个函数调用是一系列表达式中的最后一个元素(或仅有一个元素)时,才能获得它的所有返回值。另外一种情况是:可以使用圆括号强制使函数调用只返回一个值,一个return语句如果使用圆括号将函数调用括起来将导致返回一个值。
4:unpack函数
函数unpack,接受一个数组作为输入参数,返回数组的所有元素
f = string.find
a = {"hello", "ll"}
print(f(unpack(a))) --> 3 4
5:可变参数,变长参数(...),三个点表示该函数可以接收数量不定的参数。
function fwrite(fmt, ...)
return io.write(string.format(fmt, ...))
end
注意:在3个点前有一个固定参数fmt, 具有变长参数的函数同时可以拥有任意固定的参数。
fwrite("%d%d", 4,5) fmt="%d%d", 4,5属于变长参数
6: lua函数select用于访问所有的变长参数,包括nil。调用select函数的的模式:
select( selector, ...)
调用select,必须传入一个固定的实参selector。
for i = 1, select('#' , ...) do
local arg = select(i, ...) --得到第i个参数
print(arg)
end
特别需要指出 select('#', ...)会返回所有变长参数的总数量,包括nil也计算在内。
function func(...) for i=1,select('#',...) do arg = select(i,...) print(i,arg) end end func(1,2,5,"abcd",'agagsagasl')
输出结果:
[ly@localhost testLua]$ lua test-select.lua 1 1 2 2 3 5 4 abcd 5 agagsagasl
7:深入理解closure和非局部变量(non local variable)。closure的简单定义:一个closure就是一个函数加上该函数所需访问的所有“非局部的变量“。
names = {"Peter", "Paul", "Mary"} grades = {Mary = 10, Paul = 7, Peter = 8} function sortbygrade (names, grades) table.sort(names, function (n1, n2) return grades[n1] > grades[n2] -- 比较年级 end) end传递给sort的匿名函数可以访问参数grades,而grades是外部函数sortbygrade的局部变量,注意函数sortbygrade的形参grades也属于该函数的局部变量。所以table.sort函数的第二个参数就属于一个closure。 再看以下例子:function newCounter() local i = 0 return function () -- 匿名函数 i = i + 1 return i end end c1 = newCounter() print(c1()) --> 1 print(c1()) --> 2c2 = newCOunter() print(c2()) --> 1 print(c1()) --> 3 print(c2()) --> 2c1和c2是同一个函数所创建的两个不同的closure,它们各自拥有局部变量i的独立实例。 8:lua函数尾调用 当一个函数调用是另一个函数的最后一个动作时,该调用才算是一条尾调用。比如以下代码对g函数的调用就属于尾调用: function foo(x) return g(x) end 尾调用的特性是不耗费任何栈空间,所以一个程序可以拥有无数嵌套的尾调用。