在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素.迭代器需要保留上一次成功调用的状态和下一次成功调用的状态,可以通过闭包提供的机制来实现这个任务(闭包中的外部局部变量可以用来保存状态)。一个典型的闭包结构包含两个函数:一个是闭包自己,另一个是工厂(创建闭包的函数).
function list_iter(t) local i=0 local n=table.getn(t) return function() i=i+1 if i<=n then return t[i] end end end t={10,20,30} for elem in list_iter(t) do print(elem) end
--返回的是函数 function iterator(t) local i=0 local n=table.getn(t) return function() i=i+1 if i<=n then return t[i] end end end t={10,20,30} iter=iterator(t)--获取迭代器 while true do local e=iter() if e==nil then break end print(e) end
范性for的语义:
for var_1,...,var_n in explist do block end --等价于 do local _f ,_s,_var=explist--返回迭代函数、状态常量、控制变量 while true do local var_1,...,var_n =_f(_s,_var) _var=var_1 if _var==nil then break end block end end
无状态的迭代器:不保留任何状态的迭代器,避免创建闭包花费额外的代价.
function iter(a,i) i=i+1 local v=a[i] if v then return i,v end end function _ipairs(a) return iter,a,0 end a={"one","two","three"} --调用_ipairs(a)开始循环时,获取三个值:迭代函数、状态常量a,控制变量初始值0 for i,v in _ipairs(a) do print(i,v) end
应该尽可能的写无状态的迭代器,这样循环的时候由for来保存状态;如果不能用无状态的迭代器实现,应尽可能使用闭包,尽可能不要使用table这种方式,因为创建闭包的代价要比创建table小,另外lua处理闭包要比处理table速度快些。
local iterator function allwords() local state={line=io.read(),pos=1}--使用table保存状态常量、控制变量 return iterator,state end function iterator(state) while state.line do local s,e=string.find(state.line,"%w+",state.pos) if s then state.pos=e+1 return string.sub(state.line,s,e) else state.line=io.read() state.pos=1 end return nil end end