詞法定界:當一個函數內嵌套另一個函數的時候,內函數可以訪問外部函數的局部變量,這種特徵叫做詞法定界
table.sort(names,functin (n1,n2) return grades[n1]>grades[n2] end) //內部匿名函數可以訪問外部函數的n1,n2
第一類值:lua當中函數是一個值,他可以存在變量中,可以作爲函數參數,可以作爲返回值
function test() local i=0 return function() i++ ... end end //函數作爲返回值,這裏的i也叫外部局部變量,就是lua中的upvalue
閉包:通過調用含有一個內部函數加上該外部函數持有的外部局部變量(upvalue)的外部函數(就是工廠)產生的一個實例函數
閉包組成:外部函數+外部函數創建的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
閉包在迭代器中的運用:迭代器需要保留上一次調用的狀態和下一次成功調用的狀態,剛好可以使用閉包的機制來實現
創建迭代器:(一定要注意迭代器只是一個生成器,他自己本身不帶循環)
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