lua-users home
lua-l archive

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


What if the __len value of the metatable of a table was used as the value of the length and tables have a default metatable that causes `t.n` to trigger __len, essentially making it the same as `#t`? Furthermore, it would work in the opposite way, where changing the value associated with the 'n' key would change __len, causing #t to change as well. Functions such as table.insert could increment the value of t.n and table.remove could decrement this value. (Or we could have table.set and table.add so that the user could choose whether or not to manipulate array length). Pairs would go unharmed as it wouldn't actually be a key in the table, just handled by the metatable.

> On Jun 27, 2016, at 8:18 PM, Coda Highland <chighland@gmail.com> wrote:
> 
>> On Mon, Jun 27, 2016 at 4:59 PM, Philipp Janda <siffiejoe@gmx.net> wrote:
>> Am 27.06.2016 um 19:29 schröbte Roberto Ierusalimschy:
>>>> 
>>>> Bingo! I'd say an `n` key with an integer value greater than or
>>>> equal to 0, but let's not nitpick. I also think this would have been
>>>> a viable alternative to the sequence concept we now have, because it
>>>> has some useful properties:
>>>> 
>>>> *  [...]
>>> 
>>> 
>>> Something that seems to be missing in this discussion is constructors:
>>> 
>>>    l = {1, 2, 3, 4, 5}
>>>    print(#l)          --> ?  (no 'l.n'...)
>> 
>> 
>> We _have_ mentioned this a few times, e.g.:
>> 
>>> *  Counting elements in table literals is cumbersome (Lua could help with
>>> that, though).
>> 
>> 
>> or in an earlier post:
>> 
>>> 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 in one of Tim's posts:
>> 
>>> I’m undecided if a table initializer should set the size: should
>>> {1,2} have a size of 0 or 2? What about more complex initializers?
>>> And of course there are issues with non-integral keys etc.
>> 
>> 
>> And I'm fine with both options. It all depends on how you want to sell the
>> array-style table literal syntax `{ 1, 2, 3 }`:  Is it an array constructor
>> (in which case it should set `n`), or is it syntax sugar for assigning to
>> small consecutive integer keys (in which case it should leave `n` alone).
>> 
>> Array constructors that set `n` would certainly be convenient in some
>> situations. E.g., I've recently written a function for unit testing that
>> checks that a function yields certain values when resumed with certain
>> arguments:
>> 
>>    M.yields( f, { 1, 2 }, M.resp( 2, 3 ),   -- should yield 2, 3
>>                 { 8, 9 }, M.resp( 9, 10 ),  -- should yield 9, 10
>>                 { 4, 5 }, M.resp( 5, 6 ) )  -- should return 5, 6
>> 
>> For now I use a hybrid approach for the argument arrays: If there's an `n`
>> field, I use it, otherwise I assume a proper sequence.
>> 
>>> 
>>> -- Roberto
>> 
>> Philipp
> 
> 
> My biggest hesitation with declaring {1,2,3} as an explicit array
> constructor is that it would break existing code that relies on
> pairs() to iterate over sparse "arrays" if an unexpected "n" member
> were to appear in the table. That's why I think new syntax would need
> to be invented.
> 
> /s/ Adam
>