所謂「迭代器」就是一種能夠遍歷一種集合中全部元素的機制。在Lua中,一般將迭代器表示爲函數。每調用一次函數,即返回集合中的「下一個」元素。函數
每一個迭代器都須要在每次成功調用之間保持一些狀態,這樣才能知道它所在的位置及如何步進到下一個位置。在Lua中,closure對於這類任務提供了極佳的支持,一個closure就是一種能夠訪問其外部嵌套環境中的局部變量的函數。對於closure而言,這些變量就可用於在成功調用之間保持狀態值,從而使closure能夠記住它在一次遍歷中所在的位置。固然,爲了建立一個新的closure,還必須建立它的這些「非局部的變量」。所以,一個closure一般涉及到兩個函數:closure自己和一個用於建立該closure的工廠函數。lua
示例:返回元素值的迭代器示例。spa
function values (table) local i = 0 return function () i = i + 1; return table[i] end end 本例中,values就是一個工廠,每當調用這個工廠時,它就建立一個新的closure(即迭代器自己)。這個closure將它的狀態保存在其外部變量table和i中。 每當調用這個迭代器時,它就從列表table中返回下一個值。直到最後一個元素返回後,迭代器就會返回nil,以此表示迭代器結束。
能夠在while循環中使用這個迭代器:code
table = {1,2,3} iter = values (table) --建立迭代器 while true do local element = iter() --調用迭代器 if element == nil then break end print(element) end ================================= 然而,使用泛型for則更加簡單 table = {1,2,3} for element in values(table) do print(element) end 泛型for爲一次迭代循環作了全部的簿記工做。它在內部保存了迭代器函數,所以再也不須要iter變量。它在每次新迭代時調用迭代器,並在迭代器返回nil時結束循環。
示例:遍歷當前輸入文件中全部單詞element
for word in allwords() do print() end 對於迭代器,編寫迭代器自己或許不容易,但使用它們卻很容易。 function allwords() local line = io.read() -- 當前行 local pos = 1 -- 一行中的當前位置。 return function() -- 迭代器函數 while line do --若爲有效的行內容就進入循環。 local s, e = string.find(line, "%w+" ,pos) if s then --是否找到一個單詞 pos = s + 1 --該單詞的下一個位置 return string.sub(line, s, e) --返回該單詞 else line = io.read() --沒有找到單詞,嘗試下一行 pos =1 --在第一個位置上,從新開始 end end return nil -- 沒有其他行了,遍歷結束 end end