1. 函數是第一類值閉包
能夠以下表示:函數
a={p=print}; a.p(1);
在lua中全部的,全部的函數都是匿名的。當討論函數名時,好比print,實際上指的是保存該函數的變量。lua
2.局部函數blog
在定義局部遞歸函數時,因爲原來的方法不適用,因此一點是極易出錯的遞歸
local fact =function(n) if(n==0) then return 1; else return n*fact(n-1);--有問題 end end
在lua語言編譯函數體中的fact(n-1)調用時候,局部的fact還沒有定義。所以,這個表達式會嘗試調用全局的fact而非局部的fact。因此咱們經過先定義局部變量,在定義函數的方法來解決這個問題element
local fact; fact =function(n) if(n==0) then return 1; else return n*fact(n-1);--有問題 end end
當lua語言展開局部函數語法糖時候,使用的並非以前的基本函數。get
local function foo(params) body end
的定義會被展開成it
loca foo; foo= function (params) body end
3 閉包io
經過調用含有一個內部函數加上該外部函數持有的外部局部變量(upvalue)的外部函數(就是工廠)產生的一個實例函數。編譯
function test() local i=0 return function()//尾調用 i+=1 return i end end c1=test() c2=test()//c1,c2是創建在同一個函數,同一個局部變量的不一樣實例上面的兩個不一樣的閉包 //閉包中的upvalue各自獨立,調用一次test()就會產生一個新的閉包 print(c1()) -->1 print(c1()) -->2//重複調用時每個調用都會記住上一次調用後的值,就是說i=1了已經 print(c2()) -->1//閉包不一樣因此upvalue不一樣 print(c2()) -->2
4 閉包的應用
閉包在迭代器中的運用:迭代器須要保留上一次調用的狀態和下一次成功調用的狀態,恰好可使用閉包的機制來實現
建立迭代器:(必定要注意迭代器只是一個生成器,他本身自己不帶循環)
function list_iter(t) local i=0 local n=table.getn(t) return function() i=i+1 if i<=n then return t[i] end end end //這裏的list_iter是一個工廠,每次調用都會產生一個新的閉包該閉包內部包括了upvalue(t,i,n) //所以每調用一次該函數產生的閉包那麼該閉包就會根據記錄上一次的狀態,以及返回list的下一個
迭代器的使用:
while中使用: t={10,20,90} iter=list_iter(t)//調用迭代器產生一個閉包 while true do local element=iter() if element==nil then break end print(element) end end 泛型for使用: t={10,0,29} for element in list_iter(t) do//這裏的list_iter()工廠函數只會被調用一次產生一個閉包函數,後面的每一次迭代都是用該閉包函數,而不是工廠函數 print(element) end