首页 > 解决方案 > 使用迭代器的 Lua 迭代器

问题描述

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

for el in doc:each() do ... end

我想在 Lua 中编写一个迭代器,使用这个函数进行迭代,但返回每个结果的修改。我怎样才能做到这一点?


编辑:我确定我的迭代器必须开始这样的事情,但我迷失在函数的主体中。

function myiterator()
   local f, c, v = doc:each()
   return (function(c2, v2)
      -- ??
   end), ??, ??
end

标签: luaiterator

解决方案


我不知道您的 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
-- This prints out:
-- 1a
-- 2b
-- 3c

推荐阅读