使用迭代器的Lua迭代器

使用迭代器的Lua迭代器,lua,iterator,Lua,Iterator,我有一个定义为C绑定的函数,它为迭代器提供了一个通用的: 对于文档中的el:each()do。。。结束 我想在Lua中编写一个迭代器,使用这个函数进行迭代,但返回对每个结果的修改。我该怎么做 编辑:我确信我的迭代器必须这样启动,但我在函数体中迷失了方向 函数myiterator() 局部f,c,v=doc:each() 返回(功能(c2,v2) -- ?? 完)?? 结束 您可以将迭代器包装成一个协同程序,另请参见 ——虚拟对象 本地单据={ 每个=函数() 返回对{11,22,33} 结束

我有一个定义为C绑定的函数,它为迭代器提供了一个通用的

对于文档中的el:each()do。。。结束
我想在Lua中编写一个迭代器,使用这个函数进行迭代,但返回对每个结果的修改。我该怎么做


编辑:我确信我的迭代器必须这样启动,但我在函数体中迷失了方向

函数myiterator()
局部f,c,v=doc:each()
返回(功能(c2,v2)
-- ??
完)??
结束

您可以将迭代器包装成一个协同程序,另请参见

——虚拟对象
本地单据={
每个=函数()
返回对{11,22,33}
结束
}
本地myiterator=coroutine.wrap(函数()
局部f,c,v=doc:each()
返回f、c、v
(完)
对于myiterator()do中的f、c、v
打印(f、c、v)
结束
$lua test.lua
1110
22零
33零

我不知道您的C函数是如何工作的,但这里有一个迭代器函数,它应该满足您的需要。它重复调用迭代器三元组,获取第一个返回值,并对其调用函数以返回新值:

功能图(变压器、f、c、v)
返回函数()
v=f(c,v)
如果v~=nil,那么
回流变压器(v)
结束
结束
结束
例如,这将获取表
{a',b',c'}
中的键并将其平方。忽略第二个返回值(与键对应的值):

对于map中的v(函数(x)返回x*x end,对{'a','b','c'})do
印刷品(五)
结束
您可以执行
map(函数(elem)将do\u something\u返回到(elem)end,doc:each())

使用协同程序编写
map
函数时,更容易阅读该函数:

功能图(变压器、f、c、v)
返回coroutine.wrap(函数()
对于f,c,v-do中的val
合作计划产量(变压器(val))
结束
(完)
结束
为了完整性,这些函数中的任何一个都允许您使用来自原始迭代器三元组的两个返回值:

功能映射2(变压器、f、c、v)
返回函数()
本地v2
v、 v2=f(c,v)
如果v~=nil,那么
回流变压器(v,v2)
结束
结束
结束
功能图(变压器、f、c、v)
返回coroutine.wrap(函数()
对于f,c,v-do中的v,v2
协程产量(变压器(v,v2))
结束
(完)
结束
对于map2中的v(函数(a,b)返回a..b end,对{'a','b','c'})do
印刷品(五)
结束
--这将打印出:
--1a
--2b
--3c

之前:

local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}
for x, y in doc:each() do
   print(x, y)
end
local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}

-- insert myiterator definition here

for x, y in myiterator() do
   print(x, y) -- now x and y are modified
end
输出:

1   aa
2   bb
3   cc
101 (aa)
102 (bb)
103 (cc)

之后:

local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}
for x, y in doc:each() do
   print(x, y)
end
local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}

-- insert myiterator definition here

for x, y in myiterator() do
   print(x, y) -- now x and y are modified
end
输出:

1   aa
2   bb
3   cc
101 (aa)
102 (bb)
103 (cc)

感谢那些帮助过我的人。我了解到迭代器函数不必返回2或3个值。这是一个有效的列表迭代器:

每个函数(列表)
局部i=0
返回函数()--未使用任何参数!
i=i+1
返回列表[i]
结束
结束
对于每个{'foo','bar','jim'}中的单词,请打印(单词)结尾
-->福
-->酒吧
-->吉姆
由于
every()
不返回第二个值(“不变”值),因此在每次迭代时,
nil
作为第一个参数传递给匿名函数。传递给该匿名函数的第二个值是上一次传递时从函数返回的值(或第一次传递时从
every()
返回的第三个值)…但是如果这对我们迭代没有帮助,我们就不需要使用它

因为到目前为止,没有一个答案能够完全满足我的需要,所以我最终得到了以下解决方案:

函数myiterator()
局部f,c,v=doc:each()
返回函数()
v=f(c,v)
如果v那么
--注意:不要在此处更改'v'变量,因为
--f()可能期望它与它返回的完全相同
--以便在下一次调用时正确迭代。
局部myvalue=变异(v)
返回myvalue
结束
结束
结束

我喜欢使用原始迭代器的多个返回值的“聪明”方式,并在映射中将它们捕捉为
f,c,v
。)谢谢你。这让我找到了我需要去的地方。请注意,
each()
I只返回一个值,这使代码比您的代码更简单。FWIW我发现您对
prev_x
x
的使用比每次重复使用同一个变量(根据我的回答)要稍微笨拙一些,但也许您所拥有的更好,作为正在使用的说明。