lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




On 2018-06-14 04:31 AM, siney wrote:

I think it just tell you no element been removed , you should stop to call remove again by in loop,

You can check returned value is nil to know index is invalid without triggering an error.

*发件人**: *<lua-l-bounces@lists.lua.org> 代表yan jun <ks_isaf@hotmail.com>
*答复**: *Lua mailing list <lua-l@lists.lua.org>
*日期**: *2018年6月6日星期三下午7:43
*收件人**: *"lua-l@lists.lua.org" <lua-l@lists.lua.org>
*主题**: *Question about table.remove.

here is a sample:

--====================================================

t = {1}

table.remove(t,2)    --no error, return nil

table.remove(t,3)    --throw an error: "position out of bounds"

--====================================================

"table.remove" is implemented by "tremove" in C, and here is the code about "tremove" in lua5.3:

/*=====================================================

static int tremove (lua_State *L) {
  lua_Integer size = aux_getn(L, 1, TAB_RW);
  lua_Integer pos = luaL_optinteger(L, 2, size);
  if (pos != size)  /* validate 'pos' if given */
    luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
  lua_geti(L, 1, pos);  /* result = t[pos] */
  for ( ; pos < size; pos++) {
    lua_geti(L, 1, pos + 1);
    lua_seti(L, 1, pos);  /* t[pos] = t[pos + 1] */
  }
  lua_pushnil(L);
  lua_seti(L, 1, pos);  /* t[pos] = nil */
  return 1;
}

/*=====================================================

I am curious about that why "size + 1" is the validate position?

Does the positon length+1 has a special meaning?

thanks everybody!


It is the only way to have a no-op. E.g.

len = 0
t = setmetatable({}, {__index=function(t, k) return (k >= 0 and k <= len) and k or nil end, __len=function() return len end})
table.remove(t) -- works fine, not strictly safe (removes t[0])
table.remove(t, 0) -- works fine, not strictly safe either (removes t[0])
table.remove(t, 1) -- works fine, safe (doesn't remove t[0])
len = 1
table.remove(t, 1) -- removes our element
table.remove(t, 2) -- doesn't remove our element
table.remove(t, 0) -- errors

I guess this simplifies some table.remove-using code? I still find this implementation rather odd (why not check `if t[pos] == nil and t[pos - 1] == nil then error end`, as it would improve performance in theory? then again length calculation is binary search which is pretty fast if your CPU doesn't have any memory cache (or with very large tables). I just feel like it's unnecessary complexity (in the big-O sense).)