首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用迭代器的Lua迭代器

使用迭代器的Lua迭代器
EN

Stack Overflow用户
提问于 2019-08-18 21:37:15
回答 4查看 610关注 0票数 4

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

代码语言:javascript
复制
for el in doc:each() do ... end

我想在Lua中编写一个迭代器,它使用这个函数进行迭代,但是返回对每个结果的修改。我该怎么做?

编辑:我确信我的迭代器必须启动类似的东西,但是我在函数的主体中迷失了方向。

代码语言:javascript
复制
function myiterator()
   local f, c, v = doc:each()
   return (function(c2, v2)
      -- ??
   end), ??, ??
end
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-08-19 10:00:54

代码语言:javascript
复制
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

以前:

代码语言:javascript
复制
local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}
for x, y in doc:each() do
   print(x, y)
end

输出:

代码语言:javascript
复制
1   aa
2   bb
3   cc

后:

代码语言:javascript
复制
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

输出:

代码语言:javascript
复制
101 (aa)
102 (bb)
103 (cc)
票数 2
EN

Stack Overflow用户

发布于 2019-08-19 05:39:10

我不知道您的C函数是如何工作的,但是这里有一个迭代器函数,它应该能完成您想要的任务。它反复调用迭代器三重奏,获取第一个返回值,并在其上调用一个函数来返回一个新值:

代码语言:javascript
复制
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' }中的键并对其进行平方。忽略第二个返回值(与键对应的值):

代码语言:javascript
复制
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函数时,它更容易读取:

代码语言:javascript
复制
function map(transformer, f, c, v)
    return coroutine.wrap(function ()
        for val in f, c, v do
            coroutine.yield(transformer(val))
        end
    end)
end

为了完整起见,这些函数中的任何一个将允许您使用来自原始迭代器三元组的两个返回值:

代码语言:javascript
复制
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
-- This prints out:
-- 1a
-- 2b
-- 3c
票数 2
EN

Stack Overflow用户

发布于 2019-08-19 02:25:37

您可以将迭代器包装成一个协同线,也可以参见https://www.lua.org/pil/9.3.html

代码语言:javascript
复制
-- 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
代码语言:javascript
复制
$ lua test.lua
1   11  nil
2   22  nil
3   33  nil
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57548552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档