首先看看一下閉合函數(closure),見如下代碼: 閉合函數可以用來實現迭代器(iterator)(迭代器用來遍歷集合,每調用一次函數,即返回集合中的下一個元素)。 例如:遍歷一個table的時候,我們經常使用如下方式。 我們可以用while遍歷集合,也可以用for,並且用for會容易很多,下麵看 ...
首先看看一下閉合函數(closure),見如下代碼:
1 function newCounter() 2 local i = 0 -- 非局部變數(non-local variable) 3 return function () -- 閉合函數(closure) 4 i = i + 1 5 return i 6 end 7 end 8 9 c1 = newCounter() 10 print(c1()) -- 1 11 print(c1()) -- 2 12 13 c2 = newCounter() 14 print(c2()) --1 15 print(c1()) --3 16 print(c2()) --2
閉合函數可以用來實現迭代器(iterator)(迭代器用來遍歷集合,每調用一次函數,即返回集合中的下一個元素)。
例如:遍歷一個table的時候,我們經常使用如下方式。
1 t = {'x', 'y', 'z'} 2 for k, v in ipairs(t) do 3 print(k .. " " .. v) 4 end 5 -- 列印結果 6 -- 1 x 7 -- 2 y 8 -- 3 z
我們可以用while遍歷集合,也可以用for,並且用for會容易很多,下麵看一下for的語義:
1 -- A for statement like 2 3 for var_1, ···, var_n in explist do block end 4 -- is equivalent to the code: 5 6 do 7 local f, s, var = explist 8 while true do 9 local var_1, ···, var_n = f(s, var) 10 var = var_1 11 if var == nil then break end 12 block 13 end 14 end 15 -- Note the following: 16 17 -- explist is evaluated only once. Its results are an iterator function, a state, and an initial value for the first iterator variable. 18 -- f, s, and var are invisible variables. The names are here for explanatory purposes only. 19 -- You can use break to exit a for loop. 20 -- The loop variables var_i are local to the loop; you cannot use their values after the for ends. If you need these values, then assign them to other variables before breaking or exiting the loop.
註:
1 for做的第一件事就是對in後面的表達式求值,這些表達式應該返回3個值供for保存:迭代器函數(f)、恆定狀態(s)、控制變數的初值(var),不足的值用nil補足。
2 在初始化之後,for會以恆定狀態s和控制變數var來調用迭代函數f,然後for將迭代起的返回值賦予變數列表中的變數(var_1, var_2 ..., var_n),其中var_1稱為控制變數,當返回的var_1為nil時,迴圈終止。
下麵是書中的Lua實現ipair的例子:
1 t3 = {"x", "y", "z"} 2 3 local function iter (a, i) 4 i = i + 1 5 local v = a[i] 6 if v then 7 return i, v -- 第一個返回值是控制變數 8 end 9 end 10 11 function __ipairs (a) 12 return iter, a, 0 -- 3個值,迭代器、恆定狀態、控制變數。 第一次是iter(a, 0),之後則是iter(a, i) 13 end 14 15 for i, v in __ipairs(t3) do 16 print(i .. " " .. v) 17 end 18 19 -- 輸出結果: 20 -- 1 x 21 -- 2 y 22 -- 3 z
結合上面for的語義表達式,來分析上面這段代碼,__ipairs是一個工廠,生產迭代器iter,迭代器的初始參數是a和0,即恆定狀態(a)和控制變數(i),iter的返回值是控制變數i和返回值a[i]。
pairs與ipairs類似,但key是無序的,它的迭代器函數是 Lua中的一個基本函數next,在調用next(t, k)時,k是table t的一個key,此調用會以table中的任意次序返回一組值,而調用next(t, nil)時,返回table的第一組值。若沒有下一組值的時候,next返回nil。
1 function pairs(t) 2 return next, t, nil 3 end
也可以直接使用next:
1 for k, v in next, t do 2 <loop body> 3 end