lua中的只读iterable表?

lua中的只读iterable表?,lua,lua-table,Lua,Lua Table,我想在我的Lua程序中有一个只读表。如果删除了某个键或某个键与新值关联,则必须抛出一个错误 function readonly(table) local meta = { } -- metatable for proxy local proxy = { } -- this table is always empty meta.__index = table -- refer to table for lookups meta.__newindex = funct

我想在我的Lua程序中有一个只读表。如果删除了某个键或某个键与新值关联,则必须抛出一个错误

function readonly(table)
    local meta = { } -- metatable for proxy
    local proxy = { } -- this table is always empty

    meta.__index = table -- refer to table for lookups
    meta.__newindex = function(t, key, value)
        error("You cannot make any changes to this table!")
    end

    setmetatable(proxy, meta)
    return proxy -- user will use proxy instead
end
它工作得很好

t = { }
t["Apple"] = "Red"
t[true] = "True!"
t[51] = 29

for k,v in pairs(t) do
    print(v)
end

t = readonly(t)
t[51] = 30
印刷品

Red
True!
29
input:7: You cannot make any changes to this table!
问题 现在在任何情况下都不会打印任何内容。这是因为
proxy
表中永远不会有任何内容<代码>对显然从不调用
索引
,因此无法从实际表中检索任何内容

如何使此只读表可编辑

我在Lua 5.1上,可以访问以下元方法:


您可以修改标准Lua函数
以正确使用只读表

local function readonly_newindex(t, key, value)
   error("You cannot make any changes to this table!")
end

function readonly(tbl)
   return
      setmetatable({}, {
         __index = tbl,
         __newindex = readonly_newindex
      })
end

local original_pairs = pairs

function pairs(tbl)
   if next(tbl) == nil then
      local mt = getmetatable(tbl)
      if mt and mt.__newindex == readonly_newindex then
         tbl = mt.__index
      end
   end
   return original_pairs(tbl)
end
用法:

t = { }
t["Apple"] = "Red"
t[true] = "True!"
t[51] = 29

for k,v in pairs(t) do
   print(k, v)
end

t = readonly(t)

for k,v in pairs(t) do
   print(k, v)
end

t[51] = 30
t = { }
t["Apple"] = "Red"
t[true] = "True!"
t[51] = 29

for k,v in pairs(t) do
    print(v)
end

t, tIter = readonly(t)
t[51] = 30

for k, v in tIter do
   print(v)
end

一种解决方案是为表创建一个完全自定义的迭代器

function readonly(table)
    local meta = { } -- metatable for proxy
    local proxy = { } -- this table is always empty

    meta.__index = table -- refer to table for lookups
    meta.__newindex = function(t, key, value)
        error("You cannot make any changes to this table!")
    end

    local function iter()
        return next, table
    end

    setmetatable(proxy, meta)
    return proxy, iter -- user will use proxy instead
end
用法:

t = { }
t["Apple"] = "Red"
t[true] = "True!"
t[51] = 29

for k,v in pairs(t) do
   print(k, v)
end

t = readonly(t)

for k,v in pairs(t) do
   print(k, v)
end

t[51] = 30
t = { }
t["Apple"] = "Red"
t[true] = "True!"
t[51] = 29

for k,v in pairs(t) do
    print(v)
end

t, tIter = readonly(t)
t[51] = 30

for k, v in tIter do
   print(v)
end

Lua5.2+具有_对/_ipairs元方法,因此不必显式返回/使用自定义迭代器。pairs()/ipairs()可以隐式使用该自定义迭代器。@Vlad True,这是我最初的想法,但OP使用的是5.1,因此解决方案不可用。