A more flexible table.remove

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

A more flexible table.remove

Soni "They/Them" L.
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
there's already a value.

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 }

Reply | Threaded
Open this post in threaded view
|

Re: A more flexible table.remove

Vaughan McAlley-2
On Mon, 11 Jun 2018, 02:02 Soni "They/Them" L., <[hidden email]> 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
there's already a value.

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


Reply | Threaded
Open this post in threaded view
|

Re: A more flexible table.remove

Rena
In reply to this post by Soni "They/Them" L.
On Sun, Jun 10, 2018, 12:02 Soni "They/Them" L., <[hidden email]> wrote:
- pos can be a non-integer. in which case, the value is simply removed.

That's just asking for confusion.
Reply | Threaded
Open this post in threaded view
|

Re: A more flexible table.remove

Soni "They/Them" L.


On 2018-06-11 01:10 PM, Rena wrote:
> On Sun, Jun 10, 2018, 12:02 Soni "They/Them" L., <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     - pos can be a non-integer. in which case, the value is simply
>     removed.
>
>
> That's just asking for confusion.

It's about as confusing as #.

Reply | Threaded
Open this post in threaded view
|

Re: A more flexible table.remove

Dirk Laurie-2
In reply to this post by Soni "They/Them" L.
2018-06-10 18:01 GMT+02:00 Soni "They/Them" L. <[hidden email]>:

> 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.

Personally I like the fact that table.insert and table.remove give
errors on out-of range indices, because it has helped me in debugging.

I'm not altogether sure that this post is really serious. I prefer to
read it as just another indication of the ridiculous consequences that
the nil-in-table notion would have got us in.

Reply | Threaded
Open this post in threaded view
|

Re: A more flexible table.remove

Soni "They/Them" L.


On 2018-06-12 07:12 AM, Dirk Laurie wrote:

> 2018-06-10 18:01 GMT+02:00 Soni "They/Them" L. <[hidden email]>:
>> 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.
> Personally I like the fact that table.insert and table.remove give
> errors on out-of range indices, because it has helped me in debugging.
>
> I'm not altogether sure that this post is really serious. I prefer to
> read it as just another indication of the ridiculous consequences that
> the nil-in-table notion would have got us in.
>

remind me of young me trying to use table.insert and (more importantly)
table.remove to set and unset arbitrary keys, not just integers.

because that's a thing that happened.

because it would've been nice, to be able to treat integer and
non-integer indices the same, and have the good hole-free semantics of
table.remove.

because sometimes you want your API to treat tables as arrays + maps,
not exclusively arrays (with table.remove) or exclusively maps (with
t[x]=nil). but you don't want to write workarounds yourself (`if not
pcall(table.remove, t, x) then t[x] = nil end`, I guess???).

and I happened to notice, a few days ago, that this change would also
help with the move towards nil-in-tables.

(I'd argue we can have all this and still keep errors on out-of-range,
tho... at least for table.insert.)

Reply | Threaded
Open this post in threaded view
|

Re: A more flexible table.remove

Roberto Ierusalimschy
In reply to this post by Dirk Laurie-2
> I'm not altogether sure that this post is really serious. I prefer to
> read it as just another indication of the ridiculous consequences that
> the nil-in-table notion would have got us in.

This text is quite offencive, not only for the OP.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: A more flexible table.remove

Dirk Laurie-2
2018-06-12 14:20 GMT+02:00 Roberto Ierusalimschy <[hidden email]>:
>> I'm not altogether sure that this post is really serious. I prefer to
>> read it as just another indication of the ridiculous consequences that
>> the nil-in-table notion would have got us in.
>
> This text is quite offencive, not only for the OP.

I have punished myself for the offence with a yellow card that
banishes me from posting on Lua-L for two weeks.

-- Dirk