一、函數(shù)
在Lua中,函數(shù)是作為"第一類值"(First-Class Value),這表示函數(shù)可以存儲在變量中,可以通過參數(shù)傳遞給其他函數(shù),或者作為函數(shù)的返回值(類比C/C++中的函數(shù)指針),這種特性使Lua具有極大的靈活性。
Lua對函數(shù)式編程提供了良好的支持,可以支持嵌套函數(shù)。
另外,Lua既可以調用Lua編寫的函數(shù),還可以調用C語言編寫的函數(shù)(Lua所有的標準庫都是C語言寫的)。
定義一個函數(shù)
復制代碼 代碼如下:
function hello()
print('hello')
end
hello函數(shù)不接收參數(shù),調用:hello(),雖然hello不接收參數(shù),但是還可以可以傳入?yún)?shù):hello(32)
另外如果只傳遞一個參數(shù)可以簡化成functionname arg的調用形式(注意數(shù)值不行)
復制代碼 代碼如下:
> hello '3'
hello
> hello {}
hello
> hello 3
stdin:1: syntax error near '3'
另外對變量名也不適用
復制代碼 代碼如下:
> a = 21
> print a
stdin:1: syntax error near 'a'
另外,Lua函數(shù)不支持參數(shù)默認值,可以使用or非常方便的解決(類似Javascript)
復制代碼 代碼如下:
> function f(n)
>> n = n or 0
>> print(n)
>> end
> f()
0
> f(1)
1
Lua支持返回多個值,形式上非常類似Python:
復制代碼 代碼如下:
> function f()
>> return 1,2,3
>> end
> a,b,c = f()
> print(a .. b .. c)
123
函數(shù)調用的返回值可以用于table:
復制代碼 代碼如下:
> t = {f()}
> print(t[1], t[2], t[3])
1 2 3
可見,f()返回的三個值分別稱為table的3個元素,但是情況并不總是如此:
復制代碼 代碼如下:
> t = {f(), 4}
> print(t[1], t[2], t[3])
1 4 nil
這次,f()返回的1,2,3只有1稱為table的元素;
復制代碼 代碼如下:
> t = {f(), f()}
> print(t[1], t[2], t[3], t[4], t[5])
1 1 2 3 nil
總之:只有最后一項會完整的使用所有返回值(假如是函數(shù)調用)。
對于無返回值的函數(shù),可以使用(f())的形式強行返回一個值(nil)
復制代碼 代碼如下:
> function g()
>> end
> print(g())
> print((g()))
nil
實際上,(f())形式的調用返回一個且只返回一個值
復制代碼 代碼如下:
> print((f()))
1
> print(f())
1 2 3
二、變長參數(shù)
Lua支持編程參數(shù),使用簡單(借助于table、多重賦值)
復制代碼 代碼如下:
> function f(...)
for k,v in ipairs({...}) do
print(k,v)
end
end
> f(2,3,3)
1 2
2 3
3 3
使用多重賦值的方式
復制代碼 代碼如下:
> function sum3(...)
>> a,b,c = ...
>> a = a or 0
>> b = b or 0
>> c = c or 0
>> return a + b +c
>> end
> =sum3(1,2,3,4)
6
> return sum3(1,2)
3
通常在遍歷變長參數(shù)的時候只需要使用{…},然而變長參數(shù)可能會包含一些nil;那么就可以用select函數(shù)來訪問變長參數(shù)了:select('#', …)或者 select(n, …)
select('#', …)返回可變參數(shù)的長度,select(n,…)用于訪問n到select('#',…)的參數(shù)
復制代碼 代碼如下:
> =select('#', 1,2,3)
3
> return select('#', 1,2, nil,3)
4
> =select(3, 1,2, nil,3)
nil 3
> =select(2, 1,2, nil,3)
2 nil 3
注意:Lua5.0中沒有提供…表達式,而是通過一個隱含的局部table變量arg來接收所有的變長參數(shù),arg.n表示參數(shù)的個數(shù);
三、函數(shù)式編程
函數(shù)做一個First-Class Value可以賦值給變量,用后者進行調用
復制代碼 代碼如下:
> a = function() print 'hello' end
> a()
hello
> b = a
> b()
hello
匿名函數(shù)
復制代碼 代碼如下:
> g = function() return function() print 'hello' end end
> g()()
hello
函數(shù)g返回一個匿名函數(shù);
閉包是函數(shù)式編程的一種重要特性,Lua也支持
復制代碼 代碼如下:
> g = function(a) return function() print('hello'.. a); a = a + 1 end end
> f = g(3)
> f()
hello3
> f()
hello4
四、局部函數(shù)
局部函數(shù)可以理解為在當前作用域有效的函數(shù),可以用local變量來引用一個函數(shù):
復制代碼 代碼如下:
> do
>> local lf = function() print 'hello' end
>> lf()
>> end
hello
> lf()
stdin:1: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: in ?
需要注意的是,對于遞歸函數(shù)的處理
復制代碼 代碼如下:
> do
local lf = function(n)
if n = 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
stdin:8: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:8: in function 'lf'
stdin:9: in main chunk
[C]: in ?
而應該首先聲明local lf, 在進行賦值
復制代碼 代碼如下:
do
local lf;
lf = function(n)
if n = 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
hello
hello
Lua支持一種local function(…) … end的定義形式:
復制代碼 代碼如下:
> do
local function lf(n)
if n = 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
hello
hello
> lf(3)
stdin:1: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: in ?
五、尾調用
所謂尾調用,就是一個函數(shù)返回另一個函數(shù)的返回值:
復制代碼 代碼如下:
function f()
…
return g()
end
因為調用g()后,f()中不再執(zhí)行任何代碼,所以不需要保留f()的調用桟信息;Lua做了這樣的優(yōu)化,稱為"尾調用消除",g()返回后,控制點直接返回到調用f()的地方。
這種優(yōu)化對尾遞歸非常有益,通常遞歸意味著調用桟的不斷增長,甚至可能造成堆棧溢出;而尾遞歸提供了優(yōu)化條件,編譯器可以優(yōu)化掉調用桟。
下面的遞歸函數(shù)沒有使用尾遞歸,而參數(shù)為大數(shù)時,堆棧溢出:
復制代碼 代碼如下:
> function f(n)
>> if n = 0 then
>> return 0
>> end
>> a = f(n-1)
>> return n * a
>> end
> f(10000000000)
stdin:5: stack overflow
stack traceback:
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
...
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:1: in main chunk
[C]: in ?
優(yōu)化為尾遞歸
復制代碼 代碼如下:
function f(n, now)
if n = 0 then
return now
end
return f(n-1, now*n)
end
f(10000000000, 1)
運行n久也無堆棧溢出;
您可能感興趣的文章:- Lua中的string庫(字符串函數(shù)庫)總結
- Lua中的一些常用函數(shù)庫實例講解
- Lua中的模塊與module函數(shù)詳解
- Lua中的函數(shù)知識總結
- Lua字符串庫中的幾個重點函數(shù)介紹
- Lua的table庫函數(shù)insert、remove、concat、sort詳細介紹
- Lua中的常用函數(shù)庫匯總
- Lua中的面向對象編程詳解
- Lua面向對象之類和繼承
- Lua面向對象之多重繼承、私密性詳解
- Lua面向對象編程學習筆記
- Lua中函數(shù)與面向對象編程的基礎知識整理