• Subject: Re: Proposal to enhance table.remove
• From: Alexander Chernoskutov <alecherov@...>
• Date: Sun, 11 Sep 2022 14:31:06 +0500

On 11.09.2022 13:15, Lars Müller wrote:

What if the count of values removed exceeds the stack (and thus the vararg) size?

would the return values be truncated? Would an error be thrown (probably preferable)?

I think here we should be consistent with the table.unpack() behaviour, i.e. throw an error.

When handling huge tables in a program, special considerations are unavoidable.

Just like with table.unpack() one could unpack values from a huge table in chunks to avoid stack overflow, same can be applied to the proposed  table.remove().

Here's an updated version that checks for the stack space.

//--------

static int tremove (lua_State *L) {
lua_Integer i;
lua_Integer size = aux_getn(L, 1, TAB_RW);
lua_Integer pos = luaL_optinteger(L, 2, size);
lua_Integer count = luaL_optinteger(L, 3, 1);
if(count < 0) {  /* if 'count' is negative, convert the call to 'table.remove(t, pos + count + 1, -count)' */
lua_pop(L, 2);
lua_pushinteger(L, pos + count + 1);
lua_pushinteger(L, -count);
return tremove(L);
} /* 'count' from now on is strictly non-negative */
/* check whether 'pos' is in [1, size + 1] */
luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2,
"position out of bounds");
if (l_unlikely(count >= (unsigned int)INT_MAX  ||
!lua_checkstack(L, (int)(count + 1))))
return luaL_error(L, "too many results to remove");
for(i = 0; i < count; i++)  /* push 'count' elements onto the stack starting from 'pos' */
lua_geti(L, 1, pos + i);
for (i = pos ; i <= size; i++) {  /* shift the rest */
lua_geti(L, 1, i + count);
lua_seti(L, 1, i);  /* t[pos] = t[pos + count] */
}
if(pos + count - 1 <= size) {  /* remove the tail (if present) */
for(i = size - count + 1; i <= size; i++) {
lua_pushnil(L);
lua_seti(L, 1, i);
}
}
return count;
}

//--------

```--
With regards, Alex Ch```