濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > Lua中的閉合函數(shù)、非全局函數(shù)與函數(shù)的尾調(diào)用詳解

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

熱門(mén)標(biāo)簽:百度地圖標(biāo)注位置網(wǎng)站 智能語(yǔ)音電銷的機(jī)器人 電腦外呼系統(tǒng)輻射大嗎 如何利用高德地圖標(biāo)注家 開(kāi)通400電話申請(qǐng)流程 400手機(jī)電話免費(fèi)辦理 揚(yáng)州電銷外呼系統(tǒng)軟件 武漢百應(yīng)人工智能電銷機(jī)器人 上海企業(yè)外呼系統(tǒng)排名

上一篇我們簡(jiǎn)單地介紹了Lua的函數(shù),這次,我們來(lái)點(diǎn)特別的,來(lái)介紹一下Lua的函數(shù)(小若:等等,我是不是錯(cuò)過(guò)了什么?)

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

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

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

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

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

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

這個(gè)count函數(shù)會(huì)返回另外一個(gè)函數(shù),重點(diǎn)是,這個(gè)返回的函數(shù)會(huì)使用count函數(shù)的局部變量。

先來(lái)運(yùn)行,看看效果,使用如下方式調(diào)用:

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

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

輸出結(jié)果如下:

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

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

怎么旁白不出來(lái)咆哮一下?(小若:…咳咳…為毛線會(huì)這樣?!不應(yīng)該全部都輸出1嗎??。?br />  
在這里,local i就屬于一個(gè)非局部變量,因?yàn)樗炔皇侨肿兞浚膊皇菃渭兊木植孔兞浚ㄒ驗(yàn)榱硗庖粋€(gè)函數(shù)可以反問(wèn)到它)。

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

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

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

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

這次,把i作為這個(gè)內(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ù)的用處可大著了,我們?cè)陂_(kāi)發(fā)過(guò)程中使用的頻率應(yīng)該還算比較大的~

2.非全局函數(shù)

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

來(lái)看看這樣的一個(gè)函數(shù):

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

local function mutou()
  
end

這就是一個(gè)非全局函數(shù),但,這么簡(jiǎn)單的東西我可不會(huì)拿出來(lái)說(shuō)~
 
這里我想介紹一個(gè)“語(yǔ)法糖”,上面的mutou函數(shù),其實(shí)相當(dāng)于以下的代碼:

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

local mutou;
mutou = function ()
  
end

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

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

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

mutou函數(shù)里要調(diào)用pangbai函數(shù)。
在編譯的時(shí)候,mutou函數(shù)是編譯不過(guò)的,因?yàn)檫@個(gè)時(shí)候pangbai函數(shù)未定義,換句話說(shuō),pangbai變量并不存在。
只要換一個(gè)方式就可以解決這個(gè)問(wèn)題了:

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

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

這樣編譯就沒(méi)問(wèn)題了,好吧,也許Lua里不該叫編譯,反正,不會(huì)報(bào)語(yǔ)法錯(cuò)誤了~

3.尾調(diào)用

好了,一個(gè)名詞比一個(gè)名詞要反人類。

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

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

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

function mutou()
    return count();
end

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

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

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

這就不屬于尾調(diào)用,因?yàn)檎{(diào)用完count函數(shù)之后,還要取得count的返回值,然后進(jìn)行一次加法操作,這就不符合定義了。
 
尾調(diào)用有什么意義呢?
進(jìn)行尾調(diào)用時(shí)不會(huì)耗費(fèi)多余的??臻g,比如這樣一個(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í),函數(shù)就直接返回foo(n – 1),接著就沒(méi)有后續(xù)的動(dòng)作了,所以這符合尾調(diào)用的定義。
因此,這個(gè)函數(shù)的調(diào)用不會(huì)引起棧溢出。
 
但,如果稍微改改,變成這樣:
復(fù)制代碼 代碼如下:

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

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

您可能感興趣的文章:
  • js尾調(diào)用優(yōu)化的實(shí)現(xiàn)
  • 深入理解JavaScript中的尾調(diào)用(Tail Call)
  • es6函數(shù)之尾遞歸用法實(shí)例分析
  • es6函數(shù)name屬性功能與用法實(shí)例分析
  • ES6學(xué)習(xí)筆記之字符串、數(shù)組、對(duì)象、函數(shù)新增知識(shí)點(diǎn)實(shí)例分析
  • ES6中箭頭函數(shù)的定義與調(diào)用方式詳解
  • ES6中的箭頭函數(shù)實(shí)例詳解
  • ES6記錄異步函數(shù)的執(zhí)行時(shí)間詳解
  • ES6新特性之函數(shù)的擴(kuò)展實(shí)例詳解
  • es6函數(shù)之尾調(diào)用優(yōu)化實(shí)例分析

標(biāo)簽:黑龍江 延邊 江西 張掖 新余 宜賓 武漢 嘉峪關(guān)

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Lua中的閉合函數(shù)、非全局函數(shù)與函數(shù)的尾調(diào)用詳解》,本文關(guān)鍵詞  Lua,中的,閉合,函數(shù),非,全局,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Lua中的閉合函數(shù)、非全局函數(shù)與函數(shù)的尾調(diào)用詳解》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于Lua中的閉合函數(shù)、非全局函數(shù)與函數(shù)的尾調(diào)用詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    南充市| 克山县| 瓮安县| 裕民县| 兴仁县| 光山县| 海门市| 呼伦贝尔市| 太原市| 新闻| 蚌埠市| 大城县| 余干县| 海原县| 成安县| 绩溪县| 津市市| 达日县| 石棉县| 龙陵县| 喀什市| 万荣县| 格尔木市| 垣曲县| 印江| 仁寿县| 什邡市| 安丘市| 锡林郭勒盟| 静乐县| 霍城县| 芷江| 衡南县| 上虞市| 博乐市| 永泰县| 临桂县| 潞西市| 潼南县| 博客| 察哈|