Lua 迭代器使用迭代器
2019-8-18 22:34:1
收藏:0
阅读:154
评论:4
我定义了一个作为 C 绑定的函数,提供了一个通用的 for 迭代器:
for el in doc:each() do ... end
我想用 Lua 写一个迭代器,使用这个函数进行迭代,但要返回每个结果的修改。我该怎么做?
编辑:我确定我的迭代器必须从这里开始,但我在函数体中迷失了。
function myiterator()
local f, c, v = doc:each()
return (function(c2, v2)
-- ??
end), ??, ??
end
点赞
用户9383219
我不知道你的 C 函数是如何工作的,但是这里有一个迭代器函数,可以实现你所需的功能。它反复调用迭代器三元组,取第一个返回值,并调用一个函数返回一个新值:
function map(transformer, f, c, v)
return function()
v = f(c, v)
if v ~= nil then
return transformer(v)
end
end
end
例如,这个函数将取出表 { 'a', 'b', 'c' } 中的键,并将其平方。第二个返回值(与键对应的值)被忽略:
for v in map(function (x) return x * x end, pairs { 'a', 'b', 'c' }) do
print(v)
end
你可以使用 map(function (elem) return do_something_to(elem) end, doc:each())。
使用一个协程来编写 map 函数比较容易阅读:
function map(transformer, f, c, v)
return coroutine.wrap(function ()
for val in f, c, v do
coroutine.yield(transformer(val))
end
end)
end
为了完整起见,这两个函数都可以使用原始迭代器三元组的两个返回值:
function map2(transformer, f, c, v)
return function()
local v2
v, v2 = f(c, v)
if v ~= nil then
return transformer(v, v2)
end
end
end
function map(transformer, f, c, v)
return coroutine.wrap(function ()
for v, v2 in f, c, v do
coroutine.yield(transformer(v, v2))
end
end)
end
for v in map2(function (a, b) return a .. b end, pairs { 'a', 'b', 'c' }) do
print(v)
end
-- 这将打印出:
-- 1a
-- 2b
-- 3c
2019-08-19 05:39:10
用户6834680
function myiterator()
local generator, state, prev_x = doc:each()
local function my_generator()
local x, y = generator(state, prev_x)
if x ~= nil then
prev_x = x
-- modify x, y
local modified_x = x + 100
local modified_y = "("..y..")"
-- modified_x must be non-nil
return modified_x, modified_y
end
end
return my_generator
end
Before:
local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}
for x, y in doc:each() do
print(x, y)
end
Output:
1 aa
2 bb
3 cc
After:
local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}
-- 在此处插入 myiterator 的定义
for x, y in myiterator() do
print(x, y) -- 现在 x 和 y 已被修改
end
Output:
101 (aa)
102 (bb)
103 (cc)
2019-08-19 10:00:54
用户405017
感谢那些提供帮助的人。我学到了我的迭代器函数不一定需要返回2或3个值。这是一个有效的列表迭代器:
function every(list)
local i=0
return function() -- 没有使用参数!
i = i+1
return list[i]
end
end
for word in every{'foo', 'bar', 'jim'} do print(word) end
--> foo
--> bar
--> jim
因为every()不返回第二个值(“不变”值),所以在每次迭代中作为第一参数传递了一个nil到匿名函数中。传递给匿名函数的第二个值是从函数在上一次调用返回的值(或第一次执行every()的第三个返回值)……但是如果这个值不帮助我们迭代,我们就不需要使用它。
因为迄今为止没有一个答案完全回答了我需要的问题,这里是我最终使用的解决方案:
function myiterator()
local f, c, v = doc:each()
return function()
v = f(c,v)
if v then
-- 注意:不要在这里更改`v`变量,因为
-- f()可能会期望它恰好是下一个迭代器在下一次调用时返回的值
local myvalue = mutate(v)
return myvalue
end
end
end
2019-08-19 15:08:29
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

你可以将迭代器包装成一个协程,参见https://www.lua.org/pil/9.3.html
-- dummy object local doc = { each = function() return pairs{ 11, 22, 33 } end } local myiterator = coroutine.wrap(function() local f, c, v = doc:each() return f, c, v end) for f, c, v in myiterator() do print(f, c, v) end$ lua test.lua 1 11 nil 2 22 nil 3 33 nil