问题小记之 使用 nil 索引 Lua table

2019-08-29 10:15:24 浏览数 (1)

使用 Lua 已经不少时间了,遇到 “table index is nil” 的错误也很多次了,久而久之自己便形成了 Lua table 索引不能为 nil 的概念.

但实际上,上述概念是不准确的,虽然下面的 Lua 代码确实会引起 “table index is nil” 的错误:

代码语言:javascript复制
local t = {}
-- use nil as table index
t[nil] = 0

但是如果我们仅使用 nil 为索引进行 table 取值的话,实际上并不会引起错误,仅是返回 nil 罢了:

代码语言:javascript复制
local t = {}
-- use nil as table index
-- v is nil
local v = t[nil]

网上简单搜索了一下,未找到直接相关的答案,那就直接看看 Lua 源码(5.3.5 版本)吧~

其实答案还是挺简单的:

luaH_get 函数(索引 table 取值会调用到这个函数)中对于索引为 nil 的取值直接返回了 nil (并没有报错):

代码语言:javascript复制
// 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 则直接报错了:

代码语言:javascript复制
// 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” 的概念虽然不准确,但作为开发准则的话却值得坚持~

lua

0 人点赞