Lua学习笔记-迭代器和泛型for

使用迭代器例子:

--list迭代器,返回list中
function values( t )
     local i = 0;
	 local n = table.getn(t)--table中元素个数
	 --print(n)--打印出表中元素的个数
     return function() i = i + 1
		return t[i]
		end
end
tb = {11,22,33, 44, 55, 66}
--while方式调用
iter = values(tb)--创建闭包变量的参数为函数参数
while true do
	local element=iter()--调用闭包时的参数为匿名函数的参数
	if element == nil then break
	end
	print(element)
end
--for的方式
for v in values(tb) do
     print(v)
end
泛型for簿记(bookkeeping)所有迭代循环,首先调用迭代工厂,并内部保存迭代函数。每次迭代时调用新的迭代函数。但迭代器返回nil循环结束。

上面使用while的时候,其迭代器有个瑕疵:每次循环时需要创建一个新的闭包,而不能运用之前已经创建好了的closure变量,如果在这个循环外再加一个循环进行迭代时,这就成了一个很繁琐并且容易出错的问题。
创建闭包是需要代价的,只是大部分情况下都没问题,然而有些情况却是不能容忍这个代价的。这时的解决方法是使用泛型for。泛型for本身保存迭代状态,包括迭代函数,状态常量,控制变量,因此不必付出闭包的代价,称这种迭代器为无状态迭代器。

泛型for的语法:
for in do
    
end
是变量列表,我们称变量列表中的第一个变量为控制变量,其值为nil时循环结束
是表达式列表,通常只有一个值:迭代工厂的调用
执行过程:
1.初始化迭代函数,计算in后面表达式的值,表达式应该返回泛型for需要的3个值:迭代函数、状态常量、控制变量,与多值赋值一样,如果表达式返回的结果个数不足3个会自动用nil补足,多出部分则忽略。
2.将状态常量和控制变量作为参数调用迭代函数(注意:对于for结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。
3.将迭代函数返回的值赋给变量列表。
4.如果返回的第一个值为nil,则循环结束,否则执行循环体。
5.回到第2步。
更准确地说:
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
使用泛型for的结果:

--下面的例子就不必为每次的泛型for都创建一个新的closure变量了。
function iterNew(a,i)
   i=i+1
   if a[i]==nil then
		return nil,nil
   else return i,a[i]
   end
end

function ipairsnew(a)--该定义和ipairs是一样的,此处为了避免
   return iterNew,a,0--iterNew在这里只是一个函数变量,并不是调用函数
end

a={"one","two","three",'4'}
for i,v in ipairsnew(a) do
   print(i,v)
end
print("Defined by Lua:")
for i,v in ipairs(a) do--ipairs是Lua中已经定义的,与上述我们定义的ipairsnew其实是完全相同的。
   print(i,v)
end
print('use while instead of for')
--泛型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
--遍历文件中的所有匹配的单词
如果迭代函数是f,状态常量是s,控制变量的初始值为a0,那么控制变量将循环:a1=f(s,a0),a2=f(s,a1),....直到ai=nil
注明:标准库提供了几种迭代器,包括用于迭代文件中每行的(io.lines)、 迭代 table 元素的(pairs)、迭代数组元素的(ipairs)、迭代字符串中单词的(string.gmatch )。注意各自的使用场景。

你可能感兴趣的:(Lua)