函数
lua的函数以function关键字开始,后跟函数名称和参数,最后以end结束,我们看一个简单的函数定义:
1 function foo() 2 --do something 3 end 4 5 function add(a, b) 6 return a + b 7 end
在载入脚本时,函数不会执行,仅仅是会被载入内存和名称关联起来。
另外需要注意的是,调用的函数必须是在代码上方进行了定义的函数,否则运行时会报错,如下:
1 print(add(5, 10))--运行时这里会报错, 因为 add 还没有被载入到内存 2 3 function add(a, b) 4 return a + b 5 end 6 7 print(add(5, 10))--正常调用
参数
在调用函数时,也需要将对应的参数放在一对圆括号中,即使调用函数时没有参数,也必须写出一对空括号。对于这个规则只有一种特殊的例外情况:一个函数若只有一个参数,并且此参数是一个字符串或table构造式,那么圆括号便可以省略掉:
1 print "hello1" 2 print("hello2") 3 4 function foo(a) 5 print(a) 6 end 7 8 foo {1, 2, 3, 4} 9 foo({1, 2, 3})
函数的参数可以看做该函数体内的一个局部变量,调用函数时提供的实参数量可以与形参数量不同。Lua会自动调整实参的数量,以匹配参数表的要求,若“实参多余形参,则舍弃多余的实参;若实参不足,则多余的形参初始化为nil”:
1 function foo(a, b, c) 2 print(a, b, c) 3 end 4 5 foo(100, 200, 300, 400)--100 200 300 6 foo(100, 200)--100 200 nil 7 foo()--nil nil nil
变长参数
使用“...”来定义参数,Lua会在函数中定义一个名为arg的table对象来保存传递的所有参数,如下:
1 function foo(...) 2 --arg.n 可以取得参数的长度 3 print("params length: ", arg.n) 4 --打印出所有的参数及其类型 5 for i = 1, arg.n do 6 print("param index: ", i, ", param value: ", arg[i], ", param type: ", type(arg[i])) 7 end 8 end 9 10 foo() 11 foo(1, 2, 3) 12 foo("abc", 3.14, true, {1, 2, 3})
返回值
使用return可以返回值:
1 function add(a, b) 2 return a + b 3 end 4 5 num = add(100, 200) 6 print(num)--300
Lua还支持返回多个值,返回值多余接收值,则舍弃多余的返回值;若返回值不足,则多余的接收值初始化为nil,和参数调用情况一直:
1 function foo(a, b) 2 return a + b, a * b, a - b 3 end 4 5 num1, num2, num3 = foo(100, 200) 6 print(num1, num2, num3)--300 20000 -100 7 8 num1, num2, num3, num4 = foo(100, 200) 9 print(num1, num2, num3, num4)--300 20000 -100 nil 10 11 num1, num2 = foo(100, 200) 12 print(num1, num2)--300 20000 13 14 num1 = foo(100, 200) 15 print(num1)--300
深入了解Lua的函数
在Lua中,函数与其它传统类型的值具有相同的权利。函数可以存储到变量或table中,也可以作为实参传递给其它函数,还可以作为其它函数的返回值。在Lua中有一个容易混淆的概念是,函数与所有其它值一样都是匿名的,即它们都没有名称。当讨论一个函数名时,实际上是在讨论一个持有某函数的变量,比如下面的两个函数声明方式虽然不一样但实际上在Lua看来都是一致的:
1 function foo1() 2 --do sometging 3 end 4 5 foo2 = function() 6 --do sometging 7 end
局部函数
实际上,一个函数定义实际就是一条语句(更准确地说是一条赋值语句),这条语句创建了一种类型为“函数”的值,并将这个值赋予一个变量。由于函数在Lua中就是一个普通的值,所以不仅可以将其存储在全局变量中,还可以存储在局部变量甚至table的字段中:
1 obj = {} 2 obj.add = function(a, b) 3 return a + b 4 end 5 obj.subtract = function(a, b) 6 return a - b 7 end 8 9 print(obj.add(100,200)) 10 print(obj.subtract(200,123))
再看一个例子:
1 do 2 local function add(a, b) 3 return a + b 4 end 5 local function subtract(a, b) 6 return a - b 7 end 8 9 print(add(100,200)) 10 print(subtract(200,123)) 11 end 12 13 print(add(100,200))--超出作用域, 报错 14 print(subtract(200,123))--超出作用域, 报错
闭包
闭包是由函数和与其相关的引用环境组合而成的实体。我们可以简单的理解为:子函数可以使用父函数中的局部变量,这种行为就叫做闭包。下面我们看一个经典的闭包例子:
1 function closure() 2 local i = 0--注意 i 被返回的函数使用 3 return function() 4 i = i + 1 5 return i 6 end 7 end 8 9 c1 = closure()--函数作用域已经结束, 但是由于闭包的原因, i 仍然被保留了下来 10 print(c1())--1 11 print(c1())--2 12 print(c1())--3 13 14 c2 = closure()--每次调用会产生闭包的方法, 都类似类一样会生成一个新的闭包函数, i 会重新计数 15 print(c2())--1 16 print(c2())--2 17 18 print(c1())--4 19 20 c1 = nil--闭包保留的变量 i 会被真正销毁
更多Lua闭包的内容可以参考下面这篇博文:http://cn.cocos2d-x.org/tutorial/show?id=1078