lua-users home
lua-l archive

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


On 25 June 2016 at 09:10, Philipp Janda <siffiejoe@gmx.net> wrote:
> Am 24.06.2016 um 20:32 schröbte Dirk Laurie:
>>
>> [1]
>> Tables have individual metatables. Tables freshly constructed
>> by a table literal have none. The following is an error:
>>
>>> ({24,6,2016):concat"/"  --> (not yet) 24/6/2016
>>
>>
>> Would it not be nice if tables that have no metatable fall back
>> to {__index=table}? [2] Only table.pack does not have a table as
>> first argument, and we have a precedent for that in 'string',
>> which is also the __index of a metatable but contains functions
>> cannot be used with object notation.
>
>
> Strange thing, I've been thinking about this as well, but I'm coming from a
> different direction:
>
> As I've mentioned elsewhere I'm not a big fan of the `table.pack()`
> function, but one nice thing about it is that we now have an official way to
> represent sparse tables (with that extra `n` field that `table.pack()`
> sets). Strange thing is that `table.unpack()` *does not* honor that `n`
> field although those two functions appear to be inverses of each other. What
> `table.unpack()` *does* honor is the `__len` metamethod, so I thought maybe
> `table.pack()` should set a metatable on its result. Actually, most (all?)
> of the table functions in Lua 5.3 respect metamethods now, so I wondered
> what it would take to make them work with sparse tables as well, and it's
> not that much:
>
> I already mentioned `__len`. For `t[#t+1] = x` to work you'll also need a
> `__newindex` metamethod that updates `n` if the key is an integer greater
> than `n`. Now `table.insert()` (mostly) works as well. `table.remove()`
> needs some wrapping because removing an existing element does not trigger
> `__newindex` (and assigning `nil` to `t[t.n]` probably should not shrink `n`
> if `t` is allowed to have `nil` values in it, anyway). `table.pack()` is
> wrapped to set the metatable on it's result, and `table.sort()` gets a new
> default comparator that moves `nil` values to the end of the array. And
> that's mostly it!
>
> I've attached a proof of concept. I've also added an `__index` metamethod
> for OO syntax and `__call` for table iteration via `for i,v in array do ...`
> (no need for `__next`), although I don't care much about those two features.
>
> Back to the original proposal:
>
> Lua already knows how many elements -- including `nil`s -- should be added
> to a table in a lot of cases, e.g.
>
>     { ... }  -- should be `select('#', ...)`
>     { a = 1, ... }  -- still `select('#', ...)`
>     { 1, f() }  -- should be 1 + number of return values
>     { 1, 2, 3 }  -- should be 3
>     { 1, nil, nil } -- ditto
>     { 1, 2, [4]=4 }  -- 4
>     { 1, 2, [x]=4 }  -- 2, or x if x is an integer > 2
>     { 1, 2, [x]=nil }  -- same
>
>  and could set `n` and the metatable for us automatically.
>
> The only case (I can think of) that's really missing is the empty table:
>
>     local t = {}  -- array with n=0 and metatable, or just plain table?
>
> So far I've thought of two possible solutions:
>
> 1.  new syntax sugar for creating arrays  (`local t = []`?)
> 2.  a special case in the parser for a literal `{ n = 0 }`
> 3.  a constructor function for creating arrays (hopefully somthing shorter
> than `local t = table.pack()`!)
>
>
> TL;DR: I wouldn't set a default metatable on _all_ tables, only those that
> the Lua parser deems array-like. And maybe that can also solve (or at least
> mitigate) the array-with-holes debacle ...
>
> And now, discuss! :-)
>
> Philipp
>
>
>
>>
>> [1] Since feature request season seems to be open.
>> [2] Sean will no doubt be able to cite when this exact proposal
>> was first made, unless it was before 2009.
>>
>>
>

Some history: http://lua-users.org/lists/lua-l/2011-06/msg01384.html