Lua : 尝试索引空值(nil):避免条件语句中出现错误

假设我有一个庞大的表格,像这样:

test.test[1].testing.test.test_test

这个表格不能保证存在。包含它的表也可能不存在。我希望能够这样做:

if test.test[1].testing.test.test_test then
   print("它存在!")
end

但是,如果任何索引尚未定义,这当然会给我一个"尝试索引?(空值)"的错误。因此,我经常会做这样的事情:

if test then
   if test.test then
      if test.test[1] then
         if test.test[1].testing then -- 等等

有没有更好、更少繁琐的方法来完成这个任务?

点赞
用户898073
用户898073

您可以编写一个函数,它接受一个要查找的键列表,并在找到条目时执行任何操作。以下是一个示例:

function forindices(f, table, indices)
  local entry = table

  for _,idx in ipairs(indices) do
    if type(entry) == 'table' and entry[idx] then
      entry = entry[idx]
    else
      entry = nil
      break
    end
  end

  if entry then
    f()
  end
end

test = {test = {{testing = {test = {test_test = 5}}}}}

-- 打印 "it exists"
forindices(function () print("it exists") end,
           test,
           {"test", 1, "testing", "test", "test_test"})

-- 不打印
forindices(function () print("it exists") end,
           test,
           {"test", 1, "nope", "test", "test_test"})

顺便提一下,解决这种问题的函数式编程概念是 Maybe Monad。您可能可以使用 Lua 实现单子 解决此问题,但它不是很好,因为它没有语法糖。

2016-04-08 02:21:06
用户107090
用户107090

你可以通过为 nil 设置一个 __index 元方法来避免引发错误:

debug.setmetatable(nil, { __index=function () end })
print(test.test[1].testing.test.test_test)
test = {test = {{testing = {test = {test_test = 5}}}}}
print(test.test[1].testing.test.test_test)

你也可以使用一个空表来实现:

debug.setmetatable(nil, { __index={} })
2016-04-08 11:31:07