Lua索引值为nil的值。

我一直在谷歌上搜索这个问题,但迄今为止没有结果,所以我想知道是否有人知道答案——当您对 lua 中的 nil 值进行索引时,脚本会引发错误——尝试对 'variableName' 进行索引——一个 nil 值——是否可能用 may be 一个元方法来捕获,做一些处理,而不是报错?例如,如果变量 'num' 没有被定义,并且您说 'num = 2',则可以将 __newindex 元方法设置为做一些处理,这样您就可以在堆栈上同时获得变量名——'num' 和值——'2',但是如果您说 'num[2] = 3' 并且 'num' 没有被定义,您会报错——相反,就像 __newindex 一样,我希望捕获该事件并获取 nil 变量的名称——'num' ,索引-2和设置值-3。任何帮助都将不胜感激。

点赞
用户1208078
用户1208078

你可以在全局表上覆盖__newindex元方法。

function OnNewIndex(tbl, key, value)
    if tbl[key] == nil then
        print(tostring(key).. " doesn't exist.")
    end
end

setmetatable(_G, { __newindex = OnNewIndex })

num = 15

然而,默认情况下,我不认为 Lua 有这种行为。只是做像这样的事情:

num = 15

应该只声明变量' num'为全局变量并将值15分配给它。您是否将 Lua 用作某些具有此严格检查的框架的一部分?

编辑:捕获此误差的一种简单方法而不让它冒到表面会是将赋值包装在pcall中,就像这样...

pcall(function() num[2] = 15 end)

如果打印出来,你会得到输出:

false   test2.lua:18: attempt to index global 'num' (a nil value)

这至少让你知道发生了什么,如果你命名了函数,我想您可能会尝试恢复。

function TrySetValue()
    num[2] = 15
end

local result, msg = pcall(TrySetValue)
if (not result) then
    num = {}
end

result, msg = pcall(TrySetValue)
print(result, msg)
print(num[2])

当您可以事先修复代码时,似乎需要大量工作。

2012-08-03 15:50:16
用户501459
用户501459

首先,如果您说明要解决的问题,就更容易提供帮助。您是要防止使用未初始化的全局变量吗?您可以使用元表来实现。您是希望确保脚本错误永远不会从您的应用程序中弹出吗?您可以使用 pcall 来实现。您真的只是想捕获这一个特定的使用 nil 全局变量的情况,并以某种方式恢复吗?您提供的上下文信息越多,其他人就越容易找到您可能没有想到的解决方案。

至于您描述的情况,您希望捕获 num[index],其中 numnil,您实际上无法直接检测到。

这有两部分:

  1. 当从当前环境表(也称为 _ENV_G)中读取 num 的当前值时。
  2. 当您尝试索引该值时。

您无法检测到 #2,因为 nil 不是表,所以您无法为其提供元表。

但是,您可以检测 #1。根据您的要求,您可以使用 #1 返回一个代理对象,然后允许您检测 #2,然而这将意味着没有任何全局变量将是 nil,因此像这样的逻辑将无法正常工作:

--- initialize globalFoo if it doesn't exists
if not globalFoo then
    globalFoo = CreateGlobalFoo()
    ....

当然,您始终可以像将代理对象命名为 NIL 一样执行某些操作,因此可以编写以下内容:

if globalFoo == NIL then -- globalFoo 未初始化
    globalFoo = CreateGlobalFoo()

以下是一个像这样工作的代理对象的示例:

local nil_proxy_mt = {
    __index    = function(t,k)   print('Attempted to index nil!') end,
    __newindex = function(t,k,v) print('Attempted to index nil!') end,
}

local NIL = setmetatable({}, nil_proxy_mt)

setmetatable (_G, { __index = function(t,k) return NIL end })

有了这个设置,如果您尝试这两个中的任何一个:

foo = num[2]
num[2] = 15

您将获得“尝试索引空值!”并且程序继续运行。

2012-08-03 17:18:36