lua-users home
lua-l archive

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



> On Oct 18, 2018, at 12:41 AM, Dirk Laurie <dirk.laurie@gmail.com> wrote:
> 
> * Every Lua 5.2 program you ever wrote in which somewhere the argument
> to 'ipairs' is a table with an __index metamethod, has a chance of
> being broken in Lua 5.3, because that metamethod _will_ be invoked in
> a way that probably is not the reason why you supplied it. It has
> happened three times to me, so far, and the way in which the program
> fails has on each occasion been so different that I have not really
> learnt by experience. Each time, it takes me several hours of
> debugging time.
> 
> * Lua 6.0 will very probably have some kind of mechanism to address
> the holes-in-tables problem that haunts the table library. With the
> present ipairs semantics, that mechanism may well re-break programs
> that have been fixed for Lua 5.3.
> 
> The 5.4-work1 approach solved a too-ambitious problem: allowing a
> significant nil in any field of a table. To fix the problems that new
> users have with the table library, it is only necessary to allow that
> in the range 1..#tbl.
> 
> An array subtype would solve that problem.
> 
> 1. Own __len, implicit in the subtype, if you set your own __len it is
> no longer an array.
> 2. ipairs iterates from 1 to __len, table functions use __len.
> 3. Value returned by __len is fixed when the table is created and
> can't be changed by assignment, only by functions in the table library
> (insert, remove, setlen).
> 

+1 to all this, though I’m not sure why the value of __len must be fixed (nor why the table library is privileged in this regard).

I’d also add a helper function table.setlen() (array.setlen() ???) that sets the length of an array():

t = table.setlen(t, l)
Sets the __len length of table t to l and returns the table. If l is nil or not specified, the length is set to #t. If the table does not have a metatable, an empty one is added automatically(*).

This allows a compact way to create arrays from constructors:

arr = table.setlen({12, 14, 99})

(*) I’m still worried about the expense of a meltable to hold __len. table.setlent() could magically create the necessary metatable if the table does not have one (and would HAVE to if it supports my constructor approach). As Roberto noted, older versions of Lua used a single weak table to hold the lengths of all tables, but this also seems slow and cumbersome. I suggested a dedicated field in the table struct, but others have been concerned this would tax ALL tables.

—Tim