Lua裡面可以使用for in語句來周遊table,一般會使用内置的ipairs或pairs方法,而這兩個方法會傳回疊代器(關于疊代器的相關理論知識,參考小話設計模式(十五)疊代器模式)。本文就介紹一下如何自定義疊代器。
首先我們看一下ipairs的寫法:
local tbl = {"a","b","c"}
for i, var in ipairs(tbl) do
print(i, var)
end
--1 a
--2 b
--3 c
還有pairs的寫法:
local tbl = {a="x",b="y",c="z"}
for key, var in pairs(tbl) do
print(key, var)
end
--a x
--b y
--c z
簡單來講,ipairs用來周遊數組形式的table,而pairs可以周遊任何形式的table(也包括數組形式,不過效率比ipairs低)。
那麼它們是怎麼實作的呢?我們一步一步來,首先我們實作一個疊代器方法:
local function inverse(max, idx)
if idx < max then
idx = idx + 1
return idx, -idx
end
end
使用:
for i, n in inverse, 3, 0 do
print(i, n)
end
--1 -1
--2 -2
--3 -3
我們看到in後面有三個值,第一個就是我們自定義的疊代器方法inverse,而後面兩個就是inverse方法的兩個起始參數,最大值和idx,把第三個值從0改成1的話,我們會看到列印結果是從2開始的。
那麼為什麼寫法和ipairs/pairs不一樣呢?因為ipairs/pairs并不是疊代器方法,而是疊代器的生成器方法。我們可以寫一個疊代器生成器方法:
local function toinverse(count)
return inverse, count, 0
end
使用:
for i, n in toinverse(2) do
print(i,n)
end
--1 -1
--2 -2
如果在inverse方法裡面添加:
max = max / 2
然後修改使用,改為toinverse(1024),你會發現,會從1到列印到512,這是因為inverse方法每次會把idx傳回給i(-idx傳回給n),然後再次調用的時候,會把i作為第二個參數idx傳給inverse,也就是說使用i儲存了idx的狀态,而max的狀态卻沒有地方儲存。那麼如果想儲存max的狀态該怎麼辦呢?
這裡我們考慮使用閉包:
local function inversenumber(max)
local m = max
return function(max, idx)
m = m / 2
if idx < m then
idx = idx + 1
return idx, -idx
end
end
,count,0
end
使用:
for i, n in inversenumber(1024) do
print(i, n)
end
會從1列印到7。
我們這裡使用m來儲存最大值的狀态,這就跟疊代器方法的參數max沒有關系了。