比起前面提到的协同程序和过滤器,我觉的迭代器和协同程序的结合会看起来简单一些。
我们知道一个迭代器,是要遍历每一个元素。
而lua的迭代器,其实只是描述了迭代一次的过程,循环是由外置的循环语句完成的。
我们继续在之前提到的泛型for和迭代器的组合里加入协同函数。
function progrem(a,n)
if n == 0 then
coroutine.yield(a)
else
for i = 1,n do
a[n],a[i] = a[i],a[n]
progrem(a,n-1)
a[n],a[i] = a[i],a[n]
end
end
end
function itor(a,n)
return coroutine.wrap(function () progrem(a,n) end)
end
function printResult(a)
for i,v in ipairs(a) do
io.write(v," ")
end
io.write("\n")
end
do
for value in itor({1,2,3,4},4) do
printResult(value)
end
end
我们从最后一个代码块看起,泛型for中 value 的值来自于迭代器生成器 itor 生成的迭代器返回的值。
在最初提到泛型for和迭代器的时候,迭代器会通过return语句返回一个值给value,这个值通常来源于迭代器自身计算的结果。
现在迭代器和协同程序结合,会发现,迭代器 return 回来的数据,也是协同函数通过 coroutine.yield(x)函数传递回来的。而迭代的过程会被隐藏。
上述的列子,是将传入的table内容,列出所有的序列。看上述的代码的时候,建议不要太执着于具体实现,要明确迭代器和协同程序之间是如何传递参数的。
简述一下程序流程:
1、for循环开始之后,泛型for调用itor()创建了一个协同函数作为迭代器保留到泛型for中,
这里要讲一下 coroutine.wrap()函数,它也是用于创建协同函数的,和create不同的是,create返回的是一个协同(可以理解成一个编号?)而wrap返回的是一个函数。
每次调用这个返回的函数的时候,它会自己调用resume函数唤醒协同,并且返回yiled的参数,但是不会返回状态。(resume的返回值包括协同状态和yiled的参数)
2、循环开始,不停的调用迭代函数进行迭代。每次迭代完成,会通过yiled的参数返回结果。
迭代器和协同程序的结合,我觉得很大程度上扩展了迭代函数,可以把具体怎么实现迭代过程,和获取迭代结果两部分分开,感觉比较灵活。