一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Lua - Lua中的函數(function)、可變參數、局部函數、尾遞歸優化等實例講解

Lua中的函數(function)、可變參數、局部函數、尾遞歸優化等實例講解

2020-04-11 11:18iCode0410 Lua

這篇文章主要介紹了Lua中的函數(function)、可變參數、局部函數、尾遞歸優化等實例講解,需要的朋友可以參考下

一、函數

在Lua中,函數是作為"第一類值"(First-Class Value),這表示函數可以存儲在變量中,可以通過參數傳遞給其他函數,或者作為函數的返回值(類比C/C++中的函數指針),這種特性使Lua具有極大的靈活性。
 
Lua對函數式編程提供了良好的支持,可以支持嵌套函數。
 
另外,Lua既可以調用Lua編寫的函數,還可以調用C語言編寫的函數(Lua所有的標準庫都是C語言寫的)。
 
定義一個函數

復制代碼 代碼如下:

function hello()
print('hello')
end

 

hello函數不接收參數,調用:hello(),雖然hello不接收參數,但是還可以可以傳入參數:hello(32)
 
另外如果只傳遞一個參數可以簡化成functionname arg的調用形式(注意數值不行)

復制代碼 代碼如下:

> hello '3'
hello
> hello {}
hello
> hello 3
stdin:1: syntax error near '3'


 
另外對變量名也不適用

復制代碼 代碼如下:

> a = 21
> print a
stdin:1: syntax error near 'a'


 
另外,Lua函數不支持參數默認值,可以使用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


 
函數調用的返回值可以用于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


 
總之:只有最后一項會完整的使用所有返回值(假如是函數調用)。
 
對于無返回值的函數,可以使用(f())的形式強行返回一個值(nil)

復制代碼 代碼如下:

> function g()
>> end
> print(g())
 
> print((g()))
nil


實際上,(f())形式的調用返回一個且只返回一個值

復制代碼 代碼如下:

> print((f()))
1
> print(f())
1        2        3

 

二、變長參數

Lua支持編程參數,使用簡單(借助于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


通常在遍歷變長參數的時候只需要使用{…},然而變長參數可能會包含一些nil;那么就可以用select函數來訪問變長參數了:select('#', …)或者 select(n, …)

 

select('#', …)返回可變參數的長度,select(n,…)用于訪問n到select('#',…)的參數

復制代碼 代碼如下:

> =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來接收所有的變長參數,arg.n表示參數的個數;

 

三、函數式編程

函數做一個First-Class Value可以賦值給變量,用后者進行調用

復制代碼 代碼如下:

> a = function() print 'hello' end
> a()
hello
> b = a
> b()
hello


匿名函數

復制代碼 代碼如下:

> g = function() return function() print 'hello' end end
> g()()
hello


函數g返回一個匿名函數;
 
閉包是函數式編程的一種重要特性,Lua也支持

復制代碼 代碼如下:

> g = function(a) return function() print('hello'.. a); a = a + 1 end end
> f = g(3)
> f()
hello3
> f()
hello4

 

四、局部函數

局部函數可以理解為在當前作用域有效的函數,可以用local變量來引用一個函數:

復制代碼 代碼如下:

> 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 ?

 

需要注意的是,對于遞歸函數的處理

復制代碼 代碼如下:

> 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 ?

 

五、尾調用

所謂尾調用,就是一個函數返回另一個函數的返回值:

復制代碼 代碼如下:

function f()

return g()
end

 
因為調用g()后,f()中不再執行任何代碼,所以不需要保留f()的調用桟信息;Lua做了這樣的優化,稱為"尾調用消除",g()返回后,控制點直接返回到調用f()的地方。
 
這種優化對尾遞歸非常有益,通常遞歸意味著調用桟的不斷增長,甚至可能造成堆棧溢出;而尾遞歸提供了優化條件,編譯器可以優化掉調用桟。
 
下面的遞歸函數沒有使用尾遞歸,而參數為大數時,堆棧溢出:

復制代碼 代碼如下:

> 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 ?


優化為尾遞歸

復制代碼 代碼如下:

function f(n, now)
if n <= 0 then
return now
end
 
return f(n-1, now*n)
end
f(10000000000, 1)


運行n久也無堆棧溢出;

 

延伸 · 閱讀

精彩推薦
  • LuaLua簡介、編譯安裝教程及變量等語法介紹

    Lua簡介、編譯安裝教程及變量等語法介紹

    這篇文章主要介紹了Lua簡介、編譯安裝教程及變量等語法介紹,本文同時講解了lua注釋語法、Lua命令行方式等內容,需要的朋友可以參考下 ...

    junjie3632020-04-14
  • Lua深入探究Lua中的解析表達式

    深入探究Lua中的解析表達式

    這篇文章主要介紹了深入探究Lua中的解析表達式,對于其語法部分的說明和示例都超詳細,極力推薦此文!需要的朋友可以參考下 ...

    腳本之家3542020-05-05
  • LuaLua中計算、執行字符串中Lua代碼的方法

    Lua中計算、執行字符串中Lua代碼的方法

    這篇文章主要介紹了Lua中計算、執行字符串中Lua代碼的方法,類似JavaScript中eval函數的功能,在Lua中也可以實現,需要的朋友可以參考下 ...

    腳本之家6322020-04-30
  • LuaLua和C語言的交互詳解

    Lua和C語言的交互詳解

    這篇文章主要介紹了Lua和C語言的交互詳解,Lua和C語言通過棧完成交互,本文結合代碼實例詳細講解了交互的方法,需要的朋友可以參考下 ...

    果凍想3702020-04-14
  • LuaLua中table庫函數方法介紹

    Lua中table庫函數方法介紹

    這篇文章主要介紹了Lua中table庫函數方法介紹,本文講解了concat、insert、maxn、remove、sort、foreachi等方法,需要的朋友可以參考下 ...

    腳本之家2502020-04-17
  • LuaLua教程(二):基礎知識、類型與值介紹

    Lua教程(二):基礎知識、類型與值介紹

    這篇文章主要介紹了Lua教程(二):基礎知識、類型與值介紹,本文講解了Hello World程序、代碼規范、全局變量、類型與值等內容,需要的朋友可以參考下 ...

    腳本之家5922020-04-28
  • LuaLua實現__add方法重載示例

    Lua實現__add方法重載示例

    這篇文章主要介紹了Lua實現__add方法重載示例,本文直接給出實現代碼,需要的朋友可以參考下 ...

    腳本之家7452020-04-24
  • LuaLua中的元方法__newindex詳解

    Lua中的元方法__newindex詳解

    這篇文章主要介紹了Lua中的元方法__newindex詳解,本文講解了查詢與更新、監控賦值、通過table給另一個table賦值等內容,需要的朋友可以參考下 ...

    笨木頭8872020-04-09
主站蜘蛛池模板: 羞羞漫画免费漫画页面在线看漫画秋蝉 | jux629三浦理惠子在线播放 | 亚洲成aⅴ人片在线 | 扒开女人下面使劲桶屁股动漫 | 国产小视频免费看 | 咪咪爱网友自拍 | 国产在线精品99一卡2卡 | 亚洲国产欧美在线看片 | aaaa黄| 国产极品久久 | 欧美日韩一区二区三区免费 | 国产精品夜色视频一级区 | 日本人成年视频在线观看 | bbbbbbaaaaaa毛片| 国产亚洲视频网站 | 国内自拍视频在线观看 | 欧美亚洲一区二区三区 | 波多野结衣在线中文 | 国产高清在线观看 | 亚洲精品91香蕉综合区 | 国产精品探花一区在线观看 | 欧美久草在线 | 亚洲福利一区二区精品秒拍 | 久久re亚洲在线视频 | 欧美一区二区三区成人看不卡 | 帅老头恋帅老头同性tv | 午夜影院0606免费 | heyzo1754北岛玲在线视频 | 欧美一区二区三区精品国产 | 日韩成片| 日本福利视频网站 | 色在线亚洲视频www 色欲麻豆国产福利精品 | 黑人异族日本人hd | 欧美丝袜videohd | 男人网站视频 | 久热人人综合人人九九精品视频 | 成人在线播放 | 啪啪导航 | 亚洲AV无码乱码国产麻豆穿越 | 国产成人手机在线好好热 | 亚洲成人黄色网址 |