lua-users home
lua-l archive

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


On Fri, Aug 19, 2016 at 8:02 PM, Ross Berteig <Ross@cheshireeng.com> wrote:
> On 8/19/2016 10:13 AM, Viacheslav Usov wrote:
>>
>> This distinction is made in Lua's manual, too.
>>
>> Unless a |__len| metamethod is given, the length of a table |t| is only
>> defined if the table is a /sequence/, that is, the set of its positive
>> numeric keys is equal to/{1..n}/ for some non-negative integer /n/. In
>> that case, /n/ is its length.
>
>
> What you missed is the phrase "set of its positive numeric keys". That does
> not require that there be no non-positive numeric keys. Or that there be no
> keys that are not numbers at all, perhaps strings or any other type allowed
> as a key.
>
> That distinction is important.
>
> So t={1,2,3,4,5, x=13, y=print, [{}]="hard to index"} is certainly a
> sequence. It remains a sequence if elements at t[0] or t[-1] are defined as
> well, but those non-positive numbered keys are not part of the sequence.
>
>
> --
> Ross Berteig                               Ross@CheshireEng.com
> Cheshire Engineering Corp.           http://www.CheshireEng.com/
> +1 626 303 1602
>

At the risk of repeating myself, I'd like to make a point about the
difference between "contains" and "is a".

Lua has tables. It does not have sequences/arrays.

The approach taken seems to support treating tables as arrays when
they *are* defined as such. Here, we pretend that a table *is* an
array.

My understanding is that this decision was made to provide a clear
definition of a sequence and to avoid the ambiguity surrounding holes.
However, I believe that this is a week argument.

First, in every other computer programming language an array would not
contain any non-index keys at all. This concept is already unfamiliar
to them, but we allow it in Lua, because it is too convent not to. So
array-like tables are already extended beyond most people's
experience.

Second, in order to validate that a particular table *is* an array,
especially its length, we must inspect every key in the table.

There is one practical side effect of today's behavior is that this happens:

> x = { (function() return 10, 20, nil, 40 end)() }
> table.unpack(x)
10 20 nil 40
> x.n
nil
> #x
4
>

The above concession to convenience creates a behavior that silently
"does what you hope" at the expense of consistently following the
rules. This is very un-Lua like.

Also, this makes table.pack/unpack redundant. Is the following too difficult?

> x = table.pack( (function() return 10, 20, nil, 40 end)() )
> table.unpack(x, nil, x.n)
10 20 nil 40
> x.n
4

What is the downside of this?:
>#x
2 --> today this is 4

This is the answer that I would expect given pair's behavior.

What can be said now about the length operator? If you behave then it
is useful. If you do not, you can get results like this:

> z = {10, 20}
> #z
2
> z[4] = 40
> #z
4
> z[100] = 10000
> #z
4

With the simpler definition, we can say that the above table
*contains* (quacks like) a sequence with a length of 2.

To say it the opposite way, the values in a table that are outside of
the set of non-nil values between 1..n, where n is the highest non-nil
integer index, are not part of the array, regardless of their type.

It may offend people's general idea of an array, but it fits Lua
better and provides predictable behavior in all situations.

-- 
Andrew Starks