将 __call 元方法转化为迭代器

我正在尝试模拟其他应用程序脚本中某些函数的执行。该应用程序具有包含函数 list() 的 Lua 库,它返回一个表,其中键是字符串 UUID,值仅为字符串,例如 `local tbl = {"0000..-0000-..." = "someString",等等}。该表可以在 for 循环中进行迭代,例如

local lib = require("someLibrary.lua");

for key, value in lib.list() do
    -- 处理键和值,例如打印
end

-- 或者可以像这样使用

local tbl = lib.list();
for key, value in tbl do -- tbl 像 pairs(tbl) 一样工作,并且与顶部的代码完全相同
    -- 处理键和值,例如打印
end

所以问题是,如何实现 __call 元方法以像 pairs() 或 next() 等一样工作?

谢谢

点赞
用户107090
用户107090

pairs(tbl) 返回 next,tbl,nil

所以执行下面的代码:

setmetatable(tbl,{__call=function (t) return next,t,nil end})

然后就可以这样写:

for key, value in tbl() do
        print(key, value)
end

我认为无法避免括号 () 的使用。

2020-06-12 16:25:05
用户6758590
用户6758590

是的!我成功找到了我的问题的答案。我找到了我试图复制的库的源代码。它实际上使用本地变量来遍历表格。

以下是我如何让 lib.list()lst 正常工作的代码

函数 lib.list(filter, exact)
    如果过滤器 == nil then 过滤器 = '' 结束;
    如果确切 == nil then 确切 = false 结束;

    本地列表 = Component.list(filter, exact); --从编写在C#中的应用程序中获取表,就像一些Class.getSomeTable()一样。

    local list_mt = {}; --将其分配给上面的“list”表的元表
    local key = nil; --迭代器中将使用的键

    function list_mt.__call() --“列表”表的__call元方法
        key = next(list, key);
        如果关键 then
            返回键,列表[键]
        结束
    结束

    返回 setmetatable(list,list_mt); --返回带有包含__call元方法的分配元表的表
结束
2020-06-13 05:42:37