利用lua中的closure来实现lua迭代器以及用泛型for实现lua的无状态迭代器

lua中的有状态迭代器

迭代器就是一种遍历集合中所有元素的机制,lua中的迭代器通常使用函数来实现,当我们调用一次迭代器函数的时候,返回集合中的下一个元素,到这里,我们知道,那这个迭代器函数必须保存上一次调用时的一些状态,以便下一次调用,lua中的closure正好符合要求,我们可以把上一次调用的信息保存在closure中,然后就是我们需要一个返回这个迭代器的函数,我们可以把这个函数叫着生成迭代器的工厂函数,按照这个思路我们来完成一个简单的迭代器:
--迭代器共厂函数
function iterorCreater(collection)
    local index = 1
    --返回一个closure用来保存 index 的值
    return function()
         print(collection[index])
         index++
    end
end
下面我们只要通过迭代器工厂生成迭代器,并且去循环调用迭代器就好了:
collection={"zhou","l","h",9}
iteror = iterorCreater(collection)
while true do
	local res = iteror()
	if res then
		print(res)
	else
		break
	end
end
结果如下图:
利用lua中的closure来实现lua迭代器以及用泛型for实现lua的无状态迭代器_第1张图片
其实,lua中的泛型for循环会在内部保存迭代器函数,并在每一次循环时调用迭代器函数(不明白泛型for机制的可以先去google一下,肯定不会让你失望)这样的话上面的例子可以更简单,我们不用手动去创建迭代器函数,所有的工作交给泛型for来完成:
t={"zhou","l","h",9}
for res in iterorCreater(t) do
	print(res)
end
到这里,用closure实现lua中的有状态的迭代器就讲完了,但是,我们会发现一个问题,就是上面讲的迭代器需要每一次新的循环时,创建一个新的closure,如果我有10个类似的循坏,用上面的方法就需要创建10个closure,当同时创建的closure非常多时,必然会影响效率,所有我们引入下面的无状态迭代器来代替上述的工作,lua中的很多迭代器也是采用的无状态的迭代器

lua中的无状态迭代器

什么叫做无状态的迭代器呢?就是迭代器函数本身并不保存任何状态信息,这些状态信息全部由泛型for来保存,事实上,泛型for循环可以这样来描述,for var  in exp do ... end 其中,var表示 一个或多个变量名的列表,以逗号分隔,exp >是一个或多个表达式列表,通常是一个迭代器工厂函数,变量列表的第一个参数为控制变量,当为nil时退出循环,for循环调用时,先计算for后面的表达式,表达式返回三个值,迭代器函数,控制变量初值,恒定状态,然后以恒定状态和控制变量为参数调用迭代器函数,返回的值赋值给变量列表,再判断控制变量的值,决定是否重复上述过程,这里所有的赋值过程都是一个多重赋值的过程,多的值舍弃,不足的值补nil,有了泛型for的这种机制,我们可以不再需要closure来保存迭代状态,从而实现无状态的迭代器,比如我们可以自己实现以下lua中的ipairs()迭代器来迭代数组,迭代器工厂和迭代器函数如下:
collection = {"zhou","l","h"}

--迭代器函数
function iteror(t,index)
	index=index+1
	local value = t[index]
	if value then
		return index,value
	end
end

--迭代器工厂
function mPairs(t)
	return iteror,t,0  --分别为迭代器函数,恒定状态,控制变量初值
end

--遍历collection数组中的元素
for k,v in mPairs(collection) do
	print(k.."=="..v)
end
调用上述代码后产生的结果和使用调用ipairs()的结果是一样的,这里就不再演示了
要是自己又去看过lua的库中的pairs()函数,会发现也是与上述ipairs的实现类似的,只不过把我们自己写的迭代器函数换成了lua中的一个基本函数 next(),有兴趣的可以自己去实现一下
当然lua中的迭代器还有更复杂的,也可以使用协同来实现迭代等等。
写博客的目的为与大家分享一下自己的心得,交流一下自己的所学,水平有限,有不正确的地方欢迎大家批评指出。

你可能感兴趣的:(lua)