lua-users home
lua-l archive

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


Am 25.06.2016 um 22:49 schröbte Sean Conner:
It was thus said that the Great Tim Hill once stated:

Ignoring syntax and compatibility issues for a moment, what would you have
if a table had an explicit, unambiguous, first-class array length?

— No confusion over the meaning/behavior of ipairs().

What about `ipairs()` is confusing? It's just like with C strings: the first `NUL`/`nil` terminates the thing. Normal Lua tables on the other hand are like Pascal strings that only remember their capacities, not their sizes, so you have to find the (or a) terminating `nil` anyway.

— # would always be meaningful for all tables.
— table.pack() and table.unpack() would mirror each other exactly.
— The awkward “.n” convention could be scrapped.
— Arrays could contain nil values.
— Lua could potentially use the declared length to optimize internal table structure.
— Far fewer posts here on people not understanding #, sequences, and ipairs().

Of course there are all sorts of issues; if an array has length 4 what
does t[5] = 10 do? Should table.insert() automatically lengthen an array
when appending?

Not just when appending.

And others. But I really wonder if these issues are any
worse than the current odd mix of sometimes using #, sometimes stopping at
the first nil, and sometimes using “.n”.

   An idea I had was to just keep track of the largest integer key seen and
treat that as the length of the array.  It seemed to me like a no brainer
because of the structure of a table:

	typedef struct Table {
	  ...
	  unsigned int sizearray;  /* size of 'array' array */
	  TValue *array;  /* array part */
	  ..
	} Table;

That's roughly what my proof of concept does, but using the `n` field instead of some internal C field because so far the main argument against it was that many tables don't need a size, so you would waste CPU and memory. My POC only does so for array-like tables.


and tables like { 1 , 2 , nil , nil , nil , 6 } would have a length of '6'.

   But then the issue of sparse arrays and table.insert() and table.remove()
come into play.  Follow along here ... I do:

	t = { [15] = "first" }

Right now, in standard Lua, #t==0.  With my thought experiment, #t=15.  Next

	table.insert(t,"second")

still works, because now the table is { [15] = "first" , [16] = "second" }
and all is fine, until

	table.insert(t,1,"Ha ha!  I cut in line!")

Items 15 and 16 are stored in the hash portion, not the array portion.  Item
1 is (possibly?) stored in the array portion.  Should we go through and
renumber 15 and 16 to 16 and 17?

That's what already happens in Lua 5.3 (if you have a proper `__len` metamethod).

 Or not?  The same issue with
table.remove():

	table.remove(t,13)	-- remove the unlucky member

The difference with `table.remove()` is that you cannot update the length in `__newindex` because you are (most likely) assigning to an existing field at the end.


   So it was a nice idea, but an utter failure in the actual world.

Not at all. It works fine (in Lua 5.3) with some small modifications to the `table` functions. See my POC.


   -spc (Darn practice!  Always destroying beautiful theories!)

Philipp