本文简单介绍了使用 nil 索引 Lua table 的一些问题
使用 Lua 已经不少时间了,遇到 “table index is nil” 的错误也很多次了,久而久之自己便形成了 Lua table 索引不能为 nil 的概念.
但实际上,上述概念是不准确的,虽然下面的 Lua 代码确实会引起 “table index is nil” 的错误:
local t = {}
-- use nil as table index
t[nil] = 0
但是如果我们仅使用 nil 为索引进行 table 取值的话,实际上并不会引起错误,仅是返回 nil 罢了:
local t = {}
-- use nil as table index
-- v is nil
local v = t[nil]
网上简单搜索了一下,未找到直接相关的答案,那就直接看看 Lua 源码(5.3.5 版本)吧~
其实答案还是挺简单的:
luaH_get 函数(索引 table 取值会调用到这个函数)中对于索引为 nil 的取值直接返回了 nil (并没有报错):
// ltable.c
const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key));
case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
// return nil when key is nil
case LUA_TNIL: return luaO_nilobject;
case LUA_TNUMFLT: {
lua_Integer k;
if (luaV_tointeger(key, &k, 0)) /* index is int? */
return luaH_getint(t, k); /* use specialized version */
/* else... */
} /* FALLTHROUGH */
default:
return getgeneric(t, key);
}
}
而在 luaH_newkey 函数中(索引 table 赋值会调用到这个函数),如果索引为 nil 则直接报错了:
// ltable.c
TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp;
TValue aux;
// error when key is nil
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
// ...
}
不过从开发角度来讲,个人还是建议统一规避 index 为 nil 的情况,上面提及的 “Lua table 索引不能为 nil” 的概念虽然不准确,但作为开发准则的话却值得坚持~