亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

Lua中的函數知識總結

2024-07-21 23:04:11
字體:
來源:轉載
供稿:網友

前言

Lua中的函數和C++中的函數的含義是一致的,Lua中的函數格式如下:

 

復制代碼 代碼如下:

function MyFunc(param)
     -- Do something
end

在調用函數時,也需要將對應的參數放在一對圓括號中,即使調用函數時沒有參數,也必須寫出一對空括號。對于這個規則只有一種特殊的例外情況:一個函數若只有一個參數,并且此參數是一個字符串或table構造式,那么圓括號便可以省略掉。看以下代碼:
復制代碼 代碼如下:

print "Hello World"          --> print("Hello World")等價
print [[a multi-line
          message]]          -->print([[a multi-line
                              -->               message]]) 等價
-- f是一個函數
f{x=10, y=20}               -->f({x=10, y=20}) 等價

上面代碼的一些簡便寫法,如果不熟悉的話,在閱讀別人的代碼時,就會是一頭霧水。

 

一個函數定義具有一個名稱、一系列的參數和一個函數體。函數定義時,所定義的參數的使用方式與局部變量非常相似,它們是由調用函數時的“實際參數”初始化的。調用函數時提供的實參數量可以與形參數量不同。Lua會自動調整實參的數量,以匹配參數表的要求,若“實參多余形參,則舍棄多余的實參;若實參不足,則多余的形參初始化為nil”。這個與接下來要介紹的多重返回值非常相似。

多重返回值

這個應該是Lua的一個特征吧。允許函數返回多個結果,只需要在return關鍵字后列出所有的返回值即可。以下根據帶來來說明情況:

復制代碼 代碼如下:

function foo0() end                         -- 無返回值
function foo1() return "a" end          -- 返回一個結果
function foo2() return "a", "b" end     -- 返回兩個結果
 
-- 在多重賦值時,如果一個函數調用是最后,或僅有的一個表達式,
-- 那么Lua會保留其盡可能多的返回值,用于匹配賦值變量
x, y = foo2()               -- x = "a", y = "b"
x = foo2()                    -- x = "a", "b"被丟棄
x, y, z = 10, foo2()     -- x = 10, y = "a", z = "b"
 
-- 如果一個函數沒有返回值或者沒有足夠多的返回值,那么Lua會用
-- nil來補充缺失的值
x, y = foo0()               -- x = nil, y = nil
x, y = foo1()               -- x = "a", y = nil
x, y, z = foo2()          -- x = "a", y = "b", z = nil
 
-- 如果一個函數調用不是一系列表達式的最后一個元素,那么將只產生一個值:
x, y = foo2(), 20          -- x = "a", y = 20
x, y = foo0(), 20, 30     -- x = nil, y = 20, 30則被丟棄
 
-- table構造式可以完整的接收一個函數調用的所有結果,即不會有任何數量
-- 方面的調整
local t = {foo0()}          -- t = {}(一個空的table)
local t = {foo1()}          -- t = {"a"}
local t = {foo2()}          -- t = {"a", "b"}
 
-- 但是,對于上述的行為,只有當一個函數調用作為最后一個元素時才會發生,
-- 而在其他位置上的函數調用總是只產生一個結果值
local t = {foo0(), foo2(), 4}          -- t[1] = nil, t[2] = "a", t[3] = 4
 
-- 我們也可以在一個函數中,使用return返回另一個函數
function MyFunc()          -- 返回a
     return foo1()          -- 注:這里是return foo1(),而不是return (foo1())
end
 
-- return foo1()和return (foo1())是兩個完全不同的意思
-- 將一個函數調用放入一對圓括號中,從而迫使它只返回一個結果
print((foo0()))          -- nil
print((foo1()))          -- a
print((foo2()))          -- a

 

變長參數

在C語言中,函數可以接受不同數量的實參,Lua中的函數也可以接受不同數量的實參,例如以下代碼:

復制代碼 代碼如下:

-- 打印所有的參數
function VarArguments(...)
     for i, v in ipairs{...} do
          print(v)
     end
end

 

VarArguments(1, 2, 3)


參數表中的3個點(…)表示該函數可接受不同數量的實參。當這個函數被調用時,它的所有參數都會被收集到一起。這部分收集起來的實參稱為這個函數的“變長參數”。一個函數要訪問它的變長參數時,仍需要用到3個點(…)。但不同的是,此時這3個點是作為一個表達式來使用的。在上例中,表達式{…}表示一個由所有變長參數構成的數組。在C語言中使用變長參數需要注意的問題,在Lua中同樣需要注意。

 

通常一個函數在遍歷其變長參數時只需要使用表達式{…},這就像訪問一個table一樣,訪問所有的變長參數。然而在某些特殊的情況下,變長參數中可能會包含一些故意傳入的nil,那么此時就需要用select來訪問變長參數了。調用select時,必須傳入一個固定實參selector和一系列變長參數。如果selector為數字n,那么select返回它的第n個可變實參;否則selector只能為字符串“#”,這樣select會返回變長參數的總數,請看以下代碼:

復制代碼 代碼如下:

for i = 1, select('#', ...) do
    local arg = select(i, ...) -- 得到第i個參數
    -- Do something else
end

select(‘#', …)會返回所有變長參數的總數,其中包括nil(還記得table.maxn么?)對于Lua 5.0版本來說,變長參數則有另外一套機制。聲明函數的語法是一樣的,也是將3個點作為最后一個參數。但Lua 5.0沒有提供“…”表達式。而是通過一個隱含的局部table變量“arg”來接受所有的變長參數。這個table還有一個名為“n”的字段,用來記錄變長參數的總數,例如以下代碼:

 

 

復制代碼 代碼如下:

function MyFunc(a, b, ...)
     print(arg.n)
end
 
MyFunc(1, 2, 3, 4, 5)     -->3

這套舊機制的缺點在于,每當程序調用了一個具有變長參數的函數時,都會創建一個新的table。而在新機制中,只有在需要時才會去創建這個用于變長參數訪問的table。這里只是對這個方法進行簡單介紹,別在閱讀別人的代碼時,看不懂!??!

 

深入討論函數

在Lua中,函數與其它傳統類型的值具有相同的權利。函數可以存儲到變量或table中,也可以作為實參傳遞給其它函數,還可以作為其它函數的返回值。在Lua中有一個容易混淆的概念是,函數與所有其它值一樣都是匿名的,即它們都沒有名稱。當討論一個函數名時,實際上是在討論一個持有某函數的變量,例如以下代碼:

復制代碼 代碼如下:

-- 我們經常這樣定義函數
function foo(x) return 2 * x end
 
-- 實際上,這只是一種“語法糖”而已;
-- 上述代碼只是下面代碼的一種簡化書寫形式
foo = function (x) return 2 * x end

實際上,一個函數定義實際就是一條語句(更準確地說是一條賦值語句),這條語句創建了一種類型為“函數”的值,并將這個值賦予一個變量。由于函數在Lua中就是一個普通的值,所以不僅可以將其存儲在全局變量中,還可以存儲在局部變量甚至table的字段中。

 

內嵌函數

若將一個函數寫在另一個函數之內,那么這個位于內部的函數便可以訪問外部函數中的局部變量,這個特征叫做“詞法域”。我們來看看下面一段有趣的代碼:

 

復制代碼 代碼如下:

function newCounter()
     local i = 0
     return function () -- 匿名函數
          i = i + 1
          return i
     end
end
 
c1 = newCounter()
print(c1())     -->輸出什么?
print(c1())     -->又輸出什么?

如果你很明白上面的輸出,很明白上面的代碼,那么閉合函數這一小節就不需要閱讀了。在上述代碼中,有一個變量i,對于函數newCounter來說,i是一個局部變量,但是對于匿名函數來說,當它訪問這個i時,i既不是全局變量,也不是局部變量,對于我們來說,我們稱這樣的變量為一個“非局部的變量”。下面這段代碼也是同樣的道理:
復制代碼 代碼如下:

function newCounter(i)
     return function () -- 匿名函數
          i = i + 1
          return i
     end
end
 
c1 = newCounter(10)
print(c1())     -->輸出什么?
print(c1())     -->又輸出什么?

匿名函數訪問了一個“非局部的變量”i,該變量用于保持一個計數器。乍一看,由于創建變量i的函數,也就是newCounter已經返回,所以之后每次調用匿名函數時,i都應該是已經超出了作用范圍。但是,Lua會以closure的概念來正確地處理這種情況。在這里簡單的講,一個closure就是一個函數加上該函數所需訪問的所有“非局部的變量”。如果再次調用newCounter,那么它會創建一個新的局部變量i,從而將得到一個新的closure。在后續的總結中,我會專門總結一篇關于Lua中的閉包的博文,敬請期待。

 

非全局的函數

由于函數和普通變量一樣,所以函數不僅可以存儲在全局變量中,還可以存儲在table的字段中,或局部變量中。我們可以把函數存在一個table中,比如以下代碼:

 

復制代碼 代碼如下:

Lib = {}
Lib.foo = function (x, y) return x + y end
Lib.goo = function (x, y) return x - y end

只要將一個函數存儲在一個局部變量中,就得到了一個“局部函數”,也就是說這個函數只能在某個特定的作用域內才有效。我們可以這樣定義一個局部的函數:
復制代碼 代碼如下:

local f = function (<參數>)
     <函數體>
end
-- Lua還提供另一種特殊的“語法糖”
local function f (<參數>)
     <函數體>
end

有的時候,我們需要進行函數的前置聲明,比如以下代碼:
復制代碼 代碼如下:

local f, g
 
function f()
     <一些其它操作>
     g()
end
 
function g()
     <一些其它操作>
     f()
end

 

總結

這篇博文對Lua中的函數進行了大體上的總結,至少看完這篇博文,你會使用Lua寫函數了,會使用Lua中的函數了。但是對于比較深的東西,這里沒有總結,比如“閉包”。我會專門寫一篇關于Lua中的閉包的文章。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品户外野外| 一色桃子一区二区| 国产精品九九久久久久久久| 中文字幕av一区| 成人黄色片在线| 欧美另类暴力丝袜| 欧美激情精品久久久久久黑人| 中文字幕亚洲第一| 久久伊人91精品综合网站| 国语自产精品视频在线看一大j8| 国产精品第一区| 5566日本婷婷色中文字幕97| 一区二区在线视频| 欧美极品少妇xxxxⅹ喷水| 欧洲亚洲免费在线| 亚洲最新视频在线| 久久免费精品视频| 国产亚洲成av人片在线观看桃| 97精品一区二区视频在线观看| 国产成人综合精品在线| 精品一区二区电影| 亚洲免费人成在线视频观看| 孩xxxx性bbbb欧美| 日韩高清中文字幕| 欧美黄色免费网站| 欧美激情视频在线免费观看 欧美视频免费一| 国产亚洲精品美女久久久| 欧美人交a欧美精品| 成人久久久久久| 欧美劲爆第一页| 亚洲色图美腿丝袜| 亚洲高清不卡av| 国产精品午夜国产小视频| 亚洲18私人小影院| 欧美三级欧美成人高清www| 久久久久久久久久久亚洲| 亚洲日本欧美日韩高观看| 亚洲伦理中文字幕| 中文一区二区视频| 最近2019中文免费高清视频观看www99| 成人网址在线观看| 久久久久久国产精品久久| 亚洲欧美在线免费观看| 少妇激情综合网| 日韩欧美福利视频| 国产精品久久久久久久久久三级| 在线看片第一页欧美| 欧美日韩爱爱视频| 一区二区三区美女xx视频| 在线观看日韩视频| 91久久精品美女高潮| 九九热最新视频//这里只有精品| 久久精品国产2020观看福利| 亚洲人成在线电影| 欧美激情精品久久久久| 亚洲综合成人婷婷小说| 久久免费福利视频| www日韩中文字幕在线看| 久久久国产精品免费| 久久亚洲精品小早川怜子66| 国产免费一区二区三区香蕉精| 欧美日韩免费观看中文| 亚洲天堂av女优| 亚洲激情在线观看| 欧美精品在线极品| 色小说视频一区| 日本精品视频在线播放| 亚洲偷熟乱区亚洲香蕉av| 国产日韩精品电影| 日韩女在线观看| 亚洲天堂视频在线观看| 日韩欧美黄色动漫| 欧美中文字幕视频| 亚洲韩国欧洲国产日产av| 国产噜噜噜噜久久久久久久久| 欧洲s码亚洲m码精品一区| 国产精品美女免费视频| 欧美日韩一区二区在线播放| 久久成人精品一区二区三区| 亚洲最大成人免费视频| 久久久久久午夜| 亚洲免费伊人电影在线观看av| 国产ts人妖一区二区三区| 欧美多人爱爱视频网站| 精品中文字幕乱| 亚洲精品成人网| 日韩国产精品一区| 日韩视频第一页| 乱亲女秽乱长久久久| 91美女福利视频高清| 中文字幕在线视频日韩| 久久久久久久999精品视频| 日韩av免费在线| 精品国偷自产在线| 亚洲天堂av网| 亚洲一区二区久久久久久久| 色偷偷av一区二区三区| 国内伊人久久久久久网站视频| 热久久视久久精品18亚洲精品| 2019最新中文字幕| 综合136福利视频在线| 欧美日韩中文字幕日韩欧美| 亚洲日韩欧美视频一区| 日韩免费在线电影| 日韩av免费一区| 91精品综合视频| 国产精品成人va在线观看| 欧美黑人又粗大| 91精品久久久久久久久不口人| 国内精品模特av私拍在线观看| 中文字幕视频一区二区在线有码| 久久成人av网站| 亚洲a∨日韩av高清在线观看| 国内外成人免费激情在线视频网站| 欧美精品做受xxx性少妇| 91免费看片网站| 成人免费网视频| 精品无人国产偷自产在线| 亚洲男人天堂视频| 久久噜噜噜精品国产亚洲综合| 久久夜色精品亚洲噜噜国产mv| 7777免费精品视频| 亚洲影院在线看| 91精品国产综合久久久久久蜜臀| 日韩精品电影网| 亚洲视频在线播放| 国产精品久久不能| 久久久国产精品亚洲一区| 精品国产一区二区三区久久久| 国产一区二区三区在线观看网站| 久久久综合av| 992tv在线成人免费观看| 另类美女黄大片| 国产精品第2页| 久久噜噜噜精品国产亚洲综合| 精品国产91久久久| 日韩专区在线观看| 中文字幕在线看视频国产欧美| 亚洲国产精品嫩草影院久久| 色狠狠久久aa北条麻妃| 亚洲free性xxxx护士hd| 欧美成年人视频网站欧美| 亚洲理论在线a中文字幕| 欧美精品一区在线播放| 欧美第一淫aaasss性| 51色欧美片视频在线观看| 欧美日韩一区二区在线| 日韩中文字幕在线视频播放| 亚洲天堂av在线播放| 久久99视频精品| 国产精品视频中文字幕91| 亚洲美女久久久| 国产又爽又黄的激情精品视频| 亚洲va欧美va在线观看| 日韩电影中文 亚洲精品乱码| 一区二区三区在线播放欧美| 久久男人资源视频| 国产美女91呻吟求| 亚洲精品久久7777777| 亚洲a在线观看| 欧美裸体xxxx极品少妇软件| 精品高清美女精品国产区| 国产精品美女视频网站| 欧美放荡办公室videos4k|