访问深层嵌套的表没有错误?

时间:2014-05-21 09:26:39

标签: debugging lua lua-table meta-method

对于深层嵌套表中的字段,例如text.title.1.font。即使你使用

if text.title.1.font then ... end

它会导致类似&#34的错误;尝试索引全局'文本' (零值)"如果表的任何级别实际上不存在。当然,人们可能会试图检查表中每个级别的存在,但这看起来相当麻烦。我想知道是否有一种更安全,更漂亮的方法来处理这个问题,这样当引用这样的对象时,nil会是值而不是触发错误?

2 个答案:

答案 0 :(得分:1)

Egor的建议debug.setmetatable(nil, {__index = function()end})是最容易申请的。请记住,它不是词法范围的,因此,一旦打开,它将“打开”直到关闭,这可能会在代码的其他部分产生意想不到的后果。有关讨论和一些备选方案,请参阅this thread

另请注意,text.title.1.font应该是text.title[1].fonttext.title['1'].font(这两个不一样)。

另一个,更冗长,但仍然可用的替代方案是:

if (((text or {}).title or {})[1] or {}).font then ... end

答案 1 :(得分:1)

这样做不会引起大量错误的方法是明确告诉Lua默认情况下哪些表应该是表的哪些字段。你可以用metatables做到这一点。以下是一个示例,但它应该根据您希望表格的结构进行自定义。

-- This metatable is intended to catch bugs by keeping default tables empty.
local default_mt = {
  __newindex =
    function()
      error(
    'This is a default table. You have to make nested tables the old-fashioned way.')
    end
}

local number_mt = {
  __index =
    function(self, key)
      if type(key) == 'number' then
    return setmetatable({}, default_mt)
      end
    end
}

local default_number_mt = {
  __index = number_mt.__index,
  __newindex = default_mt.__newindex
}

local title_mt = {__index = {title = setmetatable({}, default_number_mt)}}

local text = setmetatable({}, title_mt)

print(text.title[1].font)