UH2S1L7——函数
函数
在Lua中,函数也是一种变量类型,而Lua的函数声明不需要指定返回值的类型
1 2 3
| function 函数名(参数列表) 函数代码块 end
|
1 2 3
| 函数名 = function(参数列表) 函数代码块 end
|
要注意,由于Lua是解释型语言,解释器从上到下执行代码,因此调用函数不能在函数声明之前,否则会报错
无参无返回值
1 2 3 4 5 6 7 8 9 10
| print("**********无参无返回值************") function F1() print("F1函数") end F1()
F2 = function() print("F2函数") end F2()
|
1 2 3
| **********无参无返回值************ F1函数 F2函数
|
通过第二种写法可以发现,在Lua中函数是一种变量类型,用起来就像是C#中的委托那样
有参数
Lua的函数声明中,参数列表是不需要写清楚参数的类型的,
因此,调用函数时,可以传入各种类型的值
(当然内部的逻辑不一定能允许你瞎写,就像下面的函数传入nil
或者boolean
就会报错)
1 2 3 4 5 6
| print("**********有参数************") function F3(a) print("参数:" .. a) end F3(1) F3("123")
|
1 2 3
| **********有参数************ 参数:1 参数:123
|
在Lua中,对一个函数不传入参数或者传入多余的参数这个行为本身不会报错(即传入参数个数与声明参数个数不匹配)
前者会让空着的参数为nil
,后者会丢弃多余的参数
1 2 3 4 5
| function FTest(a) print(a) end FTest() FTest(1, 2, 3)
|
有返回值
在函数声明时,无需声明返回值类型,而要返回值时,直接return
一个值即可
1 2 3 4 5 6
| print("**********有返回值************") function F4(a) return a end temp = F4("123") print(temp)
|
1 2
| **********有返回值************ 123
|
Lua的return
可以返回多个值,用逗号分隔即可,需要多个变量去接受它,
如果没有足够的变量接收值,则多余的返回值会被丢弃,但是对应位置的值仍然可以接收到
当然,如果有过多的变量去接收这个值,则多出的变量接收不到任何值
接收返回值的变量数量与函数中实际返回的值数量不一致,不会导致报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| print("**********有返回值************") function F4(a) return a, "456", true end temp = F4("123") print(temp) temp1, temp2, temp3 = F4("123") print(temp1) print(temp2) print(temp3) tempA, tempB, tempC, tempD = F4("******") print(tempA) print(tempB) print(tempC) print(tempD)
|
1 2 3 4 5 6 7 8 9
| **********有返回值************ 123 123 456 true ****** 456 true nil
|
函数的类型
Lua中的函数作为变量最直观的证明就是直接用type()
来输出查看返回的值
1 2 3 4 5
| print("**********函数类型************") F5 = function() print("123") end print(type(F5))
|
1 2
| **********函数类型************ function
|
可见函数在Lua中就是一种变量类型
函数重载
函数重载就是函数名相同但参数类型数量不同,返回值也不同的函数可以共同存在
Lua不支持函数重载! ,如果在之前先后声明了重名的函数 (这个行为本身不会报错!需要注意) ,则调用函数一定会调用最后声明的那个函数
1 2 3 4 5 6 7 8 9 10 11
| print("**********验证函数重载************") function F6() print("我是无参的") end
function F6(str) print(str) end
F6() F6("我是有参的")
|
1 2 3
| **********验证函数重载************ nil 我是有参的
|
如果支持函数重载,这里的返回应当分别是我是无参的
和我是有参的
,
但明显,这段代码两次调用的都是后来声明的函数,可见,Lua不支持函数重载
变长函数
不定参数在参数列表内用...
,需要一个表来接收它
1 2 3 4 5 6 7 8
| print("**********变长参数************") function F7( ... ) arg = { ... } for i = 1, #arg do print(arg[i]) end end F7(1, "2", 3, true, 5, 6)
|
1 2 3 4 5 6 7
| **********变长参数************ 1 2 3 true 5 6
|
和C#一样,参数列表中局部参数与不定参数声明可以共存,不定参数必须要在参数列表最后一位
1 2 3 4 5 6 7 8 9 10
| function FTest2(a, b, ...) print(a) print(b) print(...) arg = { ... } for i = 1, #arg do print(arg[i]) end end FTest2(1, "2", 3, true, 5, 6)
|
1 2 3 4 5 6 7
| 1 2 3 true 5 6 3 true 5 6
|
可以看到a = 1
,b = 2
,...
包括3, true, 5, 6
函数嵌套
函数作为lua中的一种变量类型,是可以在函数中返回的,
因此你可以直接返回一个函数的声明给外部(如果直接返回函数声明,则该函数声明不可以命名)
1 2 3 4 5 6 7 8 9
| print("**********函数嵌套************") function F8() return function() print(123) end end
f9 = F8() f9()
|
1 2
| **********函数嵌套************ 123
|
命名的函数也可以返回,需要先声明并赋值后再返回
1 2 3 4 5 6 7 8 9
| function Fa() Fb = function() print(123) end return Fb end
fb = Fa() fb()
|
甚至可以在函数里嵌套声明与外层函数重名的函数(不要这么做)
1 2 3 4 5 6 7 8 9
| function Fa() Fa = function() print(123) end return Fa end
fa = Fa() fa()
|
函数嵌套涉及的闭包
由于可以嵌套声明函数,以及返回函数,因此会出现函数局部变量生命周期改变的情况,也就是闭包
1 2 3 4 5 6 7 8
| function F9(x) return function(y) return x + y end end
f10 = F9(10) print(f10(5))
|
原本F9
的参数也就是局部变量x
在执行完F9
的代码后生命周期就结束了,但是F9
返回的函数仍然在使用x
这就导致局部变量x
的生命周期函数被改变,x
会在f10
存储的函数里继续使用