亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Lua中的函數(shù)知識(shí)總結(jié)

 更新時(shí)間:2014年09月29日 09:49:37   作者:果凍想  
這篇文章主要介紹了Lua中的函數(shù)知識(shí)總結(jié),本文講解了函數(shù)的一些基礎(chǔ)知識(shí)、多重返回值問題、變長(zhǎng)參數(shù)、內(nèi)嵌函數(shù)等內(nèi)容,需要的朋友可以參考下

前言

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

復(fù)制代碼 代碼如下:

function MyFunc(param)
     -- Do something
end

在調(diào)用函數(shù)時(shí),也需要將對(duì)應(yīng)的參數(shù)放在一對(duì)圓括號(hào)中,即使調(diào)用函數(shù)時(shí)沒有參數(shù),也必須寫出一對(duì)空括號(hào)。對(duì)于這個(gè)規(guī)則只有一種特殊的例外情況:一個(gè)函數(shù)若只有一個(gè)參數(shù),并且此參數(shù)是一個(gè)字符串或table構(gòu)造式,那么圓括號(hào)便可以省略掉??匆韵麓a:
復(fù)制代碼 代碼如下:

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

上面代碼的一些簡(jiǎn)便寫法,如果不熟悉的話,在閱讀別人的代碼時(shí),就會(huì)是一頭霧水。

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

多重返回值

這個(gè)應(yīng)該是Lua的一個(gè)特征吧。允許函數(shù)返回多個(gè)結(jié)果,只需要在return關(guān)鍵字后列出所有的返回值即可。以下根據(jù)帶來(lái)來(lái)說明情況:

復(fù)制代碼 代碼如下:

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

變長(zhǎng)參數(shù)

在C語(yǔ)言中,函數(shù)可以接受不同數(shù)量的實(shí)參,Lua中的函數(shù)也可以接受不同數(shù)量的實(shí)參,例如以下代碼:

復(fù)制代碼 代碼如下:

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

VarArguments(1, 2, 3)


參數(shù)表中的3個(gè)點(diǎn)(…)表示該函數(shù)可接受不同數(shù)量的實(shí)參。當(dāng)這個(gè)函數(shù)被調(diào)用時(shí),它的所有參數(shù)都會(huì)被收集到一起。這部分收集起來(lái)的實(shí)參稱為這個(gè)函數(shù)的“變長(zhǎng)參數(shù)”。一個(gè)函數(shù)要訪問它的變長(zhǎng)參數(shù)時(shí),仍需要用到3個(gè)點(diǎn)(…)。但不同的是,此時(shí)這3個(gè)點(diǎn)是作為一個(gè)表達(dá)式來(lái)使用的。在上例中,表達(dá)式{…}表示一個(gè)由所有變長(zhǎng)參數(shù)構(gòu)成的數(shù)組。在C語(yǔ)言中使用變長(zhǎng)參數(shù)需要注意的問題,在Lua中同樣需要注意。

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

復(fù)制代碼 代碼如下:

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

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

復(fù)制代碼 代碼如下:

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

這套舊機(jī)制的缺點(diǎn)在于,每當(dāng)程序調(diào)用了一個(gè)具有變長(zhǎng)參數(shù)的函數(shù)時(shí),都會(huì)創(chuàng)建一個(gè)新的table。而在新機(jī)制中,只有在需要時(shí)才會(huì)去創(chuàng)建這個(gè)用于變長(zhǎng)參數(shù)訪問的table。這里只是對(duì)這個(gè)方法進(jìn)行簡(jiǎn)單介紹,別在閱讀別人的代碼時(shí),看不懂?。?!

深入討論函數(shù)

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

復(fù)制代碼 代碼如下:

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

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

內(nèi)嵌函數(shù)

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

復(fù)制代碼 代碼如下:

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

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

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

匿名函數(shù)訪問了一個(gè)“非局部的變量”i,該變量用于保持一個(gè)計(jì)數(shù)器。乍一看,由于創(chuàng)建變量i的函數(shù),也就是newCounter已經(jīng)返回,所以之后每次調(diào)用匿名函數(shù)時(shí),i都應(yīng)該是已經(jīng)超出了作用范圍。但是,Lua會(huì)以closure的概念來(lái)正確地處理這種情況。在這里簡(jiǎn)單的講,一個(gè)closure就是一個(gè)函數(shù)加上該函數(shù)所需訪問的所有“非局部的變量”。如果再次調(diào)用newCounter,那么它會(huì)創(chuàng)建一個(gè)新的局部變量i,從而將得到一個(gè)新的closure。在后續(xù)的總結(jié)中,我會(huì)專門總結(jié)一篇關(guān)于Lua中的閉包的博文,敬請(qǐng)期待。

非全局的函數(shù)

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

復(fù)制代碼 代碼如下:

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

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

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

有的時(shí)候,我們需要進(jìn)行函數(shù)的前置聲明,比如以下代碼:
復(fù)制代碼 代碼如下:

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

總結(jié)

這篇博文對(duì)Lua中的函數(shù)進(jìn)行了大體上的總結(jié),至少看完這篇博文,你會(huì)使用Lua寫函數(shù)了,會(huì)使用Lua中的函數(shù)了。但是對(duì)于比較深的東西,這里沒有總結(jié),比如“閉包”。我會(huì)專門寫一篇關(guān)于Lua中的閉包的文章。

相關(guān)文章

  • 使用Lua作為C語(yǔ)言項(xiàng)目的配置文件實(shí)例

    使用Lua作為C語(yǔ)言項(xiàng)目的配置文件實(shí)例

    這篇文章主要介紹了使用Lua作為C語(yǔ)言項(xiàng)目的配置文件實(shí)例,本文用Lua創(chuàng)建了一個(gè)配置文件,然后在C言語(yǔ)中解析它,需要的朋友可以參考下
    2015-04-04
  • Lua所有內(nèi)置函數(shù)羅列

    Lua所有內(nèi)置函數(shù)羅列

    這篇文章主要介紹了Lua所有內(nèi)置函數(shù)羅列,本文匯集了Lua腳本語(yǔ)言的所有內(nèi)置函數(shù),需要的朋友可以參考下
    2015-04-04
  • Lua學(xué)習(xí)筆記之?dāng)?shù)據(jù)類型

    Lua學(xué)習(xí)筆記之?dāng)?shù)據(jù)類型

    這篇文章主要介紹了Lua學(xué)習(xí)筆記之?dāng)?shù)據(jù)類型,本文同時(shí)講解了開發(fā)環(huán)境的搭建,需要的朋友可以參考下
    2014-09-09
  • Lua編程示例(八):生產(chǎn)者-消費(fèi)者問題

    Lua編程示例(八):生產(chǎn)者-消費(fèi)者問題

    這篇文章主要介紹了Lua編程示例(八):生產(chǎn)者-消費(fèi)者問題,本文直接給出實(shí)例代碼,需要的朋友可以參考下
    2015-07-07
  • Lua腳本語(yǔ)言簡(jiǎn)明入門教程

    Lua腳本語(yǔ)言簡(jiǎn)明入門教程

    這篇文章主要介紹了Lua腳本語(yǔ)言簡(jiǎn)明入門教程,本文簡(jiǎn)潔干練,可以讓一個(gè)有編程基礎(chǔ)的快速的學(xué)會(huì)Lua腳本語(yǔ)言,需要的朋友可以參考下
    2014-09-09
  • Lua實(shí)現(xiàn)正序和倒序的文件讀取方法

    Lua實(shí)現(xiàn)正序和倒序的文件讀取方法

    這篇文章主要介紹了Lua實(shí)現(xiàn)正序和倒序的文件讀取方法,本文講解使用table生成鏈表完成正序和倒序的文件讀入功能,需要的朋友可以參考下
    2015-04-04
  • Lua中string.lower()使用指南

    Lua中string.lower()使用指南

    這篇文章主要介紹了Lua中操作字符串的基本方法整理,是Lua入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-08-08
  • Lua的堆棧淺析

    Lua的堆棧淺析

    這篇文章主要介紹了Lua的堆棧淺析,本文參考游戲人工智能編程案例精粹中的Lua堆棧索引圖,畫出了自己的一張理解圖,需要的朋友可以參考下
    2014-09-09
  • Lua實(shí)現(xiàn)split函數(shù)

    Lua實(shí)現(xiàn)split函數(shù)

    這篇文章主要介紹了Lua實(shí)現(xiàn)split函數(shù),lua中沒有split分割字條串函數(shù),本文使用自定義函數(shù)實(shí)現(xiàn),需要的朋友可以參考下
    2015-04-04
  • Lua腳本實(shí)現(xiàn)遞歸刪除一個(gè)文件夾

    Lua腳本實(shí)現(xiàn)遞歸刪除一個(gè)文件夾

    這篇文章主要介紹了Lua腳本實(shí)現(xiàn)遞歸刪除一個(gè)文件夾,本文給出了C++和Lua兩個(gè)版本的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2015-05-05

最新評(píng)論