• Subject: Re: A more flexible table.remove
• From: Vaughan McAlley <vaughan@...>
• Date: Mon, 11 Jun 2018 10:10:24 +1000

On Mon, 11 Jun 2018, 02:02 Soni "They/Them" L., <fakedme@gmail.com> wrote:
table.remove has some unnecessary restrictions:

> Removes from list the element at position pos, returning the value of
the removed element. When pos is an integer between 1 and #list, it
shifts down the elements list[pos+1], list[pos+2], ···, list[#list] and
erases element list[#list]; The index pos can also be 0 when #list is 0,
or #list + 1; in those cases, the function erases the element list[pos].
>
> The default value for pos is #list, so that a call table.remove(l)
removes the last element of list l.

This should be changed such that:

- pos can be a non-integer. in which case, the value is simply removed.
- pos can be negative.
- basically pos should be called index and it should just shift things
up-one or down-one when it makes sense to do so.

This allows new code to use table.remove instead of t[x] = nil. This
would start a transition period between tables-with-holes and nil-in-tables.

table.insert should be changed similarly (for consistency), with one
small difference - table.insert on non-integer indices should error if

Examples:

t = { 1, 2, 3, hello="1", world="2" }

table.remove(t, "hello") -- ok, returns "1"; t is now { 1, 2, 3, world="2" }
table.remove(t, 2) -- ok, returns 2; t is now { 1, 3, world="2" }

pcall(table.insert, t, "world", "3") -- returns nil, "attempt to insert
into an existing index"

t = { 1, 2, nil, 3, 4, 5, nil, 6, 7, 8 }

table.remove(t, 1) -- ok, returns 1; t is now { 2, nil, nil, 3, 4, 5,
nil, 6, 7, 8 }
table.insert(t, 5, 9) -- ok, t is now { 2, nil, nil, 3, 9, 4, 5, 6, 7, 8 }

If #t is cached or able to be set (which could allow nils within sequences), a successful table.remove (with possible smaller than #t) would always decrement #t, and a successful table.insert would always increment it.

Vaughan