在lua中,函数是对语句和表达式进行抽象的主要机制。函数既可以完成某项特定的任务,也可以只做一些计算并返回结果。在第一种情况中,一句函数调用被视为一句语句,而在第二种情况中,则将其视为一句表达式。如:
print(1,2) --将函数当成一句语句local a = math.sin(math.rad(30)) + math.cos(math.rad(60)) --将函数当成一句语句print(a)
无论哪种方法都需要将所有参数放在一个圆括号中。即使调用函数是没有参数,也必须写出一堆空括号。对于此规则只有一种特殊的例外情况:一个函数若只有一个参数,并且此参数是一个字面字符串或者table构造式,那么圆括号便是可有可无的。见下例:
print "hello" --等价于print("hello")print [[a b c --等价于print([[a b c d e f]] d e f]])f{x = 10,y = 20} --等价于f({x=10,y=20})
⚠ lua为面向对象式的调用也提供了一种特殊的语法-----冒号操作符。表达式o.foo(o,x)的另一种写法是o:foo(x),冒号操作符使调用o.foo时将o隐含地作为函数的第一个参数。
一个函数定义具有一个名称、一系列的参数和一个函数体。函数定义时,所定义的参数的使用方式与局部变量非常相似,它们是由调用函数时的“实际参数”初始化的。调用函数时提供的实参数量可以与形参数量不同。Lua会自动调整实参的数量,以匹配参数表的要求,若“实参多余形参,则舍弃多余的实参;若实参不足,则多余的形参初始化为nil”。
接下来我们来介绍一下多重返回值:
lua函数允许返回多个结果,只需在return关键字后列出所有的返回值即可。我们看一下例子:
function fun1() end --无返回值function fun2() return "a" end --返回一个结果function fun3() return "a","b" end --返回两个结果--在多重赋值时,如果一个函数调用时最后,或仅有的一个表达式,那么lua会保留其尽可能多的返回值,用于匹配复制变量local x,y = fun3() --x = "a", y = "b"x = fun3() --x = "a","b"被丢弃x,y,z = 10,fun3() --x = 10,y = "a",z = "b"--如果一个函数没有返回值或者没有足够多的返回值,那么lua会用nil来进行补充local x,y = fun1() --xx,y = fun2() --x = "a",y = nilx,y,z = fun3() --x = "a", y = "b", z = nil--如果一个函数调用不是一系列表达式的最后一个元素,那么将只产生一个值:local x,y = fun3(),20 --x = "a", y = 20x,y = fun1(),20,30 --x = nil,y = 20,30被丢弃x,y = 10,fun3(),20 --x = 10,y = "a"--table构造式可以完整的接收一个函数调用的所有结果,即不会有任何数量方面的调整local t = {fun1()} --t = {}local t = {fun2()} --t = {"a"}local t = {fun3()} --t = {"a","b"}--但是,对于上述的行为,只有当一个函数调用作为最后一个元素时才会发生,而在其他位置上的函数调用总是只产生一个结果值local t = {fun1(),fun3(),4} --t[1] = nil,t[2] = "a",t[3] = 4--我们也可以在一个函数中,使用return返回另一个函数function myfunction() --返回a return fun2() end--return fun2()和return(fun2())是两个完全不同的意思--将一个函数调用放入一对圆括号中,从而迫使它只返回一个结果print((fun1())) --nilprint((fun2())) --aprint((fun3())) --a
下面我们来看一下变长参数,首先我们看一个例子:
function arguments(...) for i,v in ipairs{...} do print(v) endendarguments(1,2,3)
输出为
123
参数表中的3个点(…)表示该函数可接受不同数量的实参。当这个函数被调用时,它的所有参数都会被收集到一起。这部分收集起来的实参称为这个函数的“变长参数”。一个函数要访问它的变长参数时,仍需要用到3个点(…)。但不同的是,此时这3个点是作为一个表达式来使用的。在上例中,表达式{…}表示一个由所有变长参数构成的数组。
通常一个函数在遍历其变长参数时只需要使用表达式{…},这就像访问一个table一样,访问所有的变长参数。然而在某些特殊的情况下,变长参数中可能会包含一些故意传入的nil,那么此时就需要用select来访问变长参数了。调用select时,必须传入一个固定实参selector和一系列变长参数。如果selector为数字n,那么select返回它的第n个可变实参以及其后面的所有参数;否则selector只能为字符串“#”,这样select会返回变长参数的总数。如下例:
function arguments(...) local length = select('#',...) for i=1,length do local arg = select(i,...) --得到第i个参数 print(arg) endendarguments(1,2,3,4,5,6)
输出:
123456
select(‘#’, …)会返回所有变长参数的总数,其中包括nil