在lua中,迭代器通常為函數(shù),每調(diào)用一次函數(shù),會(huì)返回集合中的下一個(gè)元素。每個(gè)迭代器在成功調(diào)用的時(shí)候,都需要保存一些狀態(tài),closure(閉包)完美為迭代器運(yùn)用而生。
function values(t)
local i=0
return function() --匿名函數(shù)
i=i+1
return t[i]
end
end
t1 ={10, 20, 30}
it=values(t1) --創(chuàng)建閉包變量的參數(shù)為函數(shù)參數(shù)
while true do
local element=it() --調(diào)用閉包時(shí)的參數(shù)為匿名函數(shù)的參數(shù)
if(element==nil) then break
end
print(element)
end
t2={11,22,33}
for v in values(t2) do
print(v)
end
--輸出結(jié)果
--10
--20
--30
--11
--22
--33
從上面的例子可以看出,范型for相對(duì)于while給我們提供了更為清晰的實(shí)現(xiàn)邏輯。luo的內(nèi)部函數(shù)已經(jīng)為我們提供了迭代函數(shù),運(yùn)行foreach時(shí)我們會(huì)調(diào)用隱式的迭代器。
上面的迭代器有一個(gè)明顯的缺點(diǎn),就是每次循環(huán)時(shí)都要?jiǎng)?chuàng)建一個(gè)新的closure變量,而不能運(yùn)用之前已經(jīng)創(chuàng)建好了的closure變量,如果我在這個(gè)循環(huán)外再加一個(gè)循環(huán)進(jìn)行迭代時(shí),這就成了一個(gè)很繁瑣并且容易出錯(cuò)的問題。
function iter(a,i)
i=i+1
if a[i]==nil then return nil,nil
else return i,a[i]
end
end
function ipairs(a)
return iter,a,0 --iter在這里只是一個(gè)函數(shù)變量,并不是調(diào)用函數(shù)
end
a={"one","two","three"}
for i,v in ipairs(a) do
print(i,v)
end
--上面的泛型for的寫法可以改為下面的while寫法
do
local _it,_s,_k=ipairs(a)
while true do
k,v=_it(_s,_k)
_k=k
if k==nil then break end
print(k,v)
end
end
--輸出結(jié)果
--1 one
--2 two
--3 three
--1 one
--2 two
--3 three
function getnext(list,node)
if not node then return list
else return node.next
end
end
function traverse(list)
return getnext,list,nil
end
list=nil
for line in io.lines() do
list={next=list, value=line}
end
for node in traverse(list) do
print(node.value)
end
--輸入
--a
--b
--c
--輸出
--c
--b
--a
通過上面的例子可以看出,可以無限次運(yùn)用list變量和調(diào)用traverse函數(shù)而不必像第一種情況那樣每次循環(huán)之前都創(chuàng)建新的closure變量。