天天看點

Lua文法小貼士(六)疊代器Lua裡面可以使用for in語句來周遊table,一般會使用内置的ipairs或pairs方法,而這兩個方法會傳回疊代器(關于疊代器的相關理論知識,參考小話設計模式(十五)疊代器模式)。本文就介紹一下如何自定義疊代器。

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沒有關系了。