最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Lua中的閉合函數(shù)、非全局函數(shù)與函數(shù)的尾調(diào)用詳解

 更新時間:2014年09月13日 10:18:55   投稿:junjie  
這篇文章主要介紹了Lua中的閉合函數(shù)、非全局函數(shù)與函數(shù)的尾調(diào)用詳解,本文對這2種函數(shù)和尾調(diào)用做了深入研究,需要的朋友可以參考下

上一篇我們簡單地介紹了Lua的函數(shù),這次,我們來點特別的,來介紹一下Lua的函數(shù)(小若:等等,我是不是錯過了什么?)

1.閉合函數(shù)(closure)

理論上來說,Lua的所有函數(shù)都應(yīng)該稱之為閉合函數(shù),但是,這種反人類的做法,我們還是拋棄吧~

按書上的描述,一個閉合函數(shù)就是:一個函數(shù)加上該函數(shù)所需訪問的所有”非局部的變量“。

理論什么的,很煩人,來看看一個函數(shù):

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

function count()
    local i = 0;
    return function()
              i = i + 1;
              return i;
           end
end

這個count函數(shù)會返回另外一個函數(shù),重點是,這個返回的函數(shù)會使用count函數(shù)的局部變量。

先來運行,看看效果,使用如下方式調(diào)用:

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

    local func = count();
    print(func());
    print(func());
    print(func());

輸出結(jié)果如下:

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

[LUA-print] 1
[LUA-print] 2
[LUA-print] 3

怎么旁白不出來咆哮一下?(小若:…咳咳…為毛線會這樣?!不應(yīng)該全部都輸出1嗎??。?br />  
在這里,local i就屬于一個非局部變量,因為它既不是全局變量,也不是單純的局部變量(因為另外一個函數(shù)可以反問到它)。

再來回到定義,count函數(shù)里的那個函數(shù),加上非局部變量i,就構(gòu)成了一個閉合函數(shù)了,就這么簡單。
 
對于閉合函數(shù)而已,屬于它的非局部變量,并不是在調(diào)用它的時候臨時產(chǎn)生的,而是和它一起存在的。

所以每次調(diào)用閉合函數(shù),非局部變量的值都不會被重置。
 
如果大家還是不太清楚,那么,我們給這個閉合函數(shù)添加一個局部變量吧,修改count函數(shù)如下:

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

function count()
    return function()
              local i = 999;
              i = i + 1;
              return i;
           end
end

這次,把i作為這個內(nèi)部函數(shù)的局部變量了,它不再是“非局部變量”。
仍然像這樣調(diào)用:

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

    local func = count();
    print(func());
    print(func());
    print(func());

輸出結(jié)果如下:

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

[LUA-print] 1000
[LUA-print] 1000
[LUA-print] 1000

陷入, 每一次i變量的值都是全新的。
閉合函數(shù)的用處可大著了,我們在開發(fā)過程中使用的頻率應(yīng)該還算比較大的~

2.非全局函數(shù)

又是這種看著就反人類的名詞,非全局,那就是說,不是全局的函數(shù)(小若:廢你個話啊?。?/p>

來看看這樣的一個函數(shù):

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

local function mutou()
  
end

這就是一個非全局函數(shù),但,這么簡單的東西我可不會拿出來說~
 
這里我想介紹一個“語法糖”,上面的mutou函數(shù),其實相當(dāng)于以下的代碼:

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

local mutou;
mutou = function ()
  
end

這就是我們函數(shù)的真實面貌,函數(shù)名稱其實也是一個變量名而已。
所以,有時候,我們在定義函數(shù)的時候,要注意一下順序。比如,這樣的兩個函數(shù):

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

local function mutou()
    print("mutou");
    return pangbai();
end
local function pangbai()
    print("pangbai");
end

mutou函數(shù)里要調(diào)用pangbai函數(shù)。
在編譯的時候,mutou函數(shù)是編譯不過的,因為這個時候pangbai函數(shù)未定義,換句話說,pangbai變量并不存在。
只要換一個方式就可以解決這個問題了:

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

local mutou;
local pangbai;
mutou = function ()
    print("mutou");
    return pangbai();
end
pangbai = function ()
    print("pangbai");
end

這樣編譯就沒問題了,好吧,也許Lua里不該叫編譯,反正,不會報語法錯誤了~

3.尾調(diào)用

好了,一個名詞比一個名詞要反人類。

尾調(diào)用的大致意思是:一個函數(shù)的調(diào)用是另一個函數(shù)的最后一個動作時,這個調(diào)用就稱之為尾調(diào)用。

比如這樣的函數(shù):

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

function mutou()
    return count();
end

當(dāng)mutou函數(shù)調(diào)用完count函數(shù)之后,就沒有其他事情要做了,所以,調(diào)用count函數(shù),就屬于尾調(diào)用。
但,如果是這樣的函數(shù):

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

function mutou()
    return count() + 1;
end

這就不屬于尾調(diào)用,因為調(diào)用完count函數(shù)之后,還要取得count的返回值,然后進(jìn)行一次加法操作,這就不符合定義了。
 
尾調(diào)用有什么意義呢?
進(jìn)行尾調(diào)用時不會耗費多余的??臻g,比如這樣一個經(jīng)典的函數(shù):

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

function foo(n)
    if n > 0 then
        return foo(n - 1);
    else
        return "end";
    end
end

我們可以試試這樣調(diào)用:

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

print(foo(99999));

 
結(jié)果就是不出所料地輸出了end字符串。
當(dāng)n > 0時,函數(shù)就直接返回foo(n – 1),接著就沒有后續(xù)的動作了,所以這符合尾調(diào)用的定義。
因此,這個函數(shù)的調(diào)用不會引起棧溢出。
 
但,如果稍微改改,變成這樣:
復(fù)制代碼 代碼如下:

function foo(n)
    if n > 0 then
        return foo(n - 1) + 0;
    else
        return "end";
    end
end

運行的時候,就會報這樣的一個錯誤: [string "src/main.lua"]:57: stack overflow
 
由于我用Lua的情況不多,所以暫時沒有舉個比較實用的例子,但,這自然會是一個很好用的特性。
 
好了,關(guān)于Lua的函數(shù),應(yīng)該都介紹完了,我也是按著書的順序在過一遍基礎(chǔ),然后把覺得有意思的部分用文章記錄下來。

相關(guān)文章

  • Lua教程(一):在C++中嵌入Lua腳本

    Lua教程(一):在C++中嵌入Lua腳本

    這篇文章主要介紹了Lua教程(一):在C++中嵌入Lua腳本,本文在MAC環(huán)境中開發(fā),同時探討了IOS項目集成Lua、Android項目集成Lua等內(nèi)容,需要的朋友可以參考下
    2014-09-09
  • Lua中的基本數(shù)據(jù)類型詳細(xì)介紹

    Lua中的基本數(shù)據(jù)類型詳細(xì)介紹

    這篇文章主要介紹了Lua中的基本數(shù)據(jù)類型詳細(xì)介紹,本文詳細(xì)的講解了Lua中的8種基本數(shù)據(jù)類型,需要的朋友可以參考下
    2014-09-09
  • Lua和C語言的交互詳解

    Lua和C語言的交互詳解

    這篇文章主要介紹了Lua和C語言的交互詳解,Lua和C語言通過棧完成交互,本文結(jié)合代碼實例詳細(xì)講解了交互的方法,需要的朋友可以參考下
    2014-09-09
  • Lua之字符串格式化例子和常用格式化參數(shù)介紹

    Lua之字符串格式化例子和常用格式化參數(shù)介紹

    這篇文章主要介紹了Lua之字符串格式化例子和常用格式化參數(shù)介紹,本文著重講解了格式化參數(shù)的作用,需要的朋友可以參考下
    2015-04-04
  • Lua中的源代碼預(yù)編譯淺析

    Lua中的源代碼預(yù)編譯淺析

    這篇文章主要介紹了Lua中的源代碼預(yù)編譯淺析,Lua確實允許在運行源代碼之前,將源代碼預(yù)編譯成一種中間形式(類比Python的.pyc),需要的朋友可以參考下
    2014-09-09
  • Lua和C++的通信流程代碼實例

    Lua和C++的通信流程代碼實例

    這篇文章主要介紹了Lua和C++的通信流程代碼實例,本文是上一篇的DEMO,本文用代碼講解Lua和C++之間的通信,需要的朋友可以參考下
    2014-09-09
  • Lua中的模塊(module)和包(package)詳解

    Lua中的模塊(module)和包(package)詳解

    這篇文章主要介紹了Lua中的模塊(module)和包(package)詳解,本文講解了require函數(shù)、寫一個模塊、package.loaded、module函數(shù)等內(nèi)容,需要的朋友可以參考下
    2014-09-09
  • Lua源碼中字符串類型的實現(xiàn)

    Lua源碼中字符串類型的實現(xiàn)

    與其他主流腳本語言不同的是,Lua在實現(xiàn)字符串類型有兩方面不同。第一,所有的字符串在Lua中都只儲存一份拷貝。第二,所有的字符串變量,只保存字符串引用,而不保存它的buffer。我們來具體看看lua源碼中如何實現(xiàn)字符串類型的吧
    2015-04-04
  • Lua多重繼承代碼實例

    Lua多重繼承代碼實例

    這篇文章主要介紹了Lua多重繼承代碼實例,本文直接給出實例代碼,需要的朋友可以參考下
    2015-04-04
  • Lua中的迭代器(iterator)淺析

    Lua中的迭代器(iterator)淺析

    這篇文章主要介紹了Lua中的迭代器(iterator)淺析,本文講解了pairs迭代器和、ipairs迭代器,同時提及了io.lines、string.gmatch、迭代器與Closure(閉包)等內(nèi)容,需要的朋友可以參考下
    2014-09-09

最新評論

桦南县| 广东省| 新沂市| 和田县| 仙游县| 张掖市| 南和县| 营口市| 赤峰市| 太仓市| 台州市| 微山县| 庆元县| 浮梁县| 衡阳市| 濮阳市| 鱼台县| 田阳县| 陆良县| 夹江县| 乐平市| 尉犁县| 楚雄市| 南雄市| 西丰县| 自贡市| 信丰县| 娱乐| 桂平市| 海城市| 隆昌县| 阳曲县| 石门县| 靖州| 德安县| 乌兰县| 永定县| 平利县| 辽阳县| 淮南市| 玉环县|