Applying the # operator on a table

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Applying the # operator on a table

Romeu Braz Pereira Gomes Filho
I was testing the # operator on a table and got some strange results.
The chunk used was:

t = {10, 20, nil, 40}
print(#t) --> 4 (should not be 2?)
t = {10, nil, nil, 40}
print(#t) --> 4 (should not be 1?)
t = {}; t[1] = 10; t[2] = 20; t[3] = nil; t[4] = 40;
print(#t) --> 4 (should not be 2?)
t = {}; t[1] = 10; t[2] = nil; t[3] = nil; t[4] = 40;
print(#t) --> 1 (OK)

Is this an expected result or a bug?

Regards,

Romeu.

Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

Matthew Wild
On 8 April 2013 14:25, Romeu Braz Pereira Gomes Filho
<[hidden email]> wrote:
> I was testing the # operator on a table and got some strange results.
> The chunk used was:
>
> t = {10, 20, nil, 40}
> print(#t) --> 4 (should not be 2?)

Read:

  - Lua 5.1: http://www.lua.org/manual/5.1/manual.html#2.5.5

  - Lua 5.2: http://www.lua.org/manual/5.2/manual.html#3.4.6

Regards,
Matthew

Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

Daniel Silverstone
In reply to this post by Romeu Braz Pereira Gomes Filho
On Mon, Apr 08, 2013 at 10:25:07AM -0300, Romeu Braz Pereira Gomes Filho wrote:
> Is this an expected result or a bug?

Expected.

The # operator is only guaranteed to return *a* boundary, not the first one.
(Where boundary is defined as t[#t] ~= nil && t[#t +1] == nil

In other words, it's only guaranteed to behave nicely in full arrays (ones with
no gaps).

D.

--
Daniel Silverstone                         http://www.digital-scurf.org/
PGP mail accepted and encouraged.            Key Id: 3CCE BABE 206C 3B69

Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

steve donovan
In reply to this post by Romeu Braz Pereira Gomes Filho
On Mon, Apr 8, 2013 at 3:25 PM, Romeu Braz Pereira Gomes Filho <[hidden email]> wrote:
Is this an expected result or a bug?

It is expected; tables-with-holes (those containing nils) are not guaranteed to work properly with #

Different versions of Lua will in fact give different results, some of them 'correct'. This is undefined behaviour
Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

Paul Cuthbertson
In reply to this post by Romeu Braz Pereira Gomes Filho
On Mon, Apr 8, 2013 at 2:25 PM, Romeu Braz Pereira Gomes Filho <[hidden email]> wrote:
Is this an expected result or a bug?

Programming in Lua, Second Edition (p.16) states:

When the array has holes — nil elements inside it — the length operator may assume any of these nil elements as the end marker. Of course, this unpredictability is hardly what you want. Therefore, you should avoid using the length operator on arrays that may contain holes. 


Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

steve donovan
In reply to this post by Daniel Silverstone
On Mon, Apr 8, 2013 at 3:29 PM, Daniel Silverstone <[hidden email]> wrote:
Expected.

Of course, in 5.2 you can redefine # on a table by giving it a metatable with the metamethod __len.  Then you can make it mean anything you like.  I think people are confused because ipairs(t) does iterate until the first 'hole', but # is meant to be fast and not do O(N) lookups

Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

liam mail
In reply to this post by Romeu Braz Pereira Gomes Filho


On 8 April 2013 14:25, Romeu Braz Pereira Gomes Filho <[hidden email]> wrote:
I was testing the # operator on a table and got some strange results.
The chunk used was:

t = {10, 20, nil, 40}
print(#t) --> 4 (should not be 2?)
t = {10, nil, nil, 40}
print(#t) --> 4 (should not be 1?)


Is this an expected result or a bug?

Regards,

Romeu.


These two are implementation defined not undefined.
Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

liam mail
Argh, infact they these are not examples of implementation defined behaviour.

--Liam

I need a "sent in 10 minutes after you brain has engaged" email setting.


On 8 April 2013 15:54, liam mail <[hidden email]> wrote:


On 8 April 2013 14:25, Romeu Braz Pereira Gomes Filho <[hidden email]> wrote:
I was testing the # operator on a table and got some strange results.
The chunk used was:

t = {10, 20, nil, 40}
print(#t) --> 4 (should not be 2?)
t = {10, nil, nil, 40}
print(#t) --> 4 (should not be 1?)


Is this an expected result or a bug?

Regards,

Romeu.


These two are implementation defined not undefined.

Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

Brad Jorsch
In reply to this post by steve donovan
On Mon, Apr 8, 2013 at 9:30 AM, steve donovan <[hidden email]> wrote:
>
> It is expected; tables-with-holes (those containing nils) are not guaranteed
> to work properly with #
>
> Different versions of Lua will in fact give different results, some of them
> 'correct'. This is undefined behaviour

In 5.1, it was defined but not deterministic.

In 5.2, the length "is only defined if the table is a sequence", but
it's not clear whether applying the length operator to such a table is
"undefined behavior" as that term is used in languages such as C.

For that matter, in 5.2 it doesn't seem to actually be defined that
the length of a table with no positive numeric keys is 0 (does the set
"{1..0}" have any more meaning than something like "{1..-1}"?). And it
seems the length of tables with positive numeric keys that are not
integers (e.g. { 'a', [1.5]='b', 'c' }) is not technically defined,
either.

Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

Roberto Ierusalimschy
> In 5.2, the length "is only defined if the table is a sequence", but
> it's not clear whether applying the length operator to such a table is
> "undefined behavior" as that term is used in languages such as C.

Not at all. Only the resulting value is undefined, not the behavior of
the operation.


> For that matter, in 5.2 it doesn't seem to actually be defined that
> the length of a table with no positive numeric keys is 0 (does the set
> "{1..0}" have any more meaning than something like "{1..-1}"?)

Both have the same "quantity" of meaning :) I read {1..n} as a shorthand
for {i | 1 <= i and i <= n}, so both {1..0} and {1..-1} denote the empty
set. (OK, so the length of an empty set could be -1, but I do not think
this is what confuses people.)


> And it seems the length of tables with positive numeric keys that
> are not integers (e.g. { 'a', [1.5]='b', 'c' }) is not technically
> defined, either.

Yes.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Applying the # operator on a table

Romeu Braz Pereira Gomes Filho
Thank you very much for all your answers.

Romeu.


On Mon, Apr 8, 2013 at 1:33 PM, Roberto Ierusalimschy <[hidden email]> wrote:
> In 5.2, the length "is only defined if the table is a sequence", but
> it's not clear whether applying the length operator to such a table is
> "undefined behavior" as that term is used in languages such as C.

Not at all. Only the resulting value is undefined, not the behavior of
the operation.


> For that matter, in 5.2 it doesn't seem to actually be defined that
> the length of a table with no positive numeric keys is 0 (does the set
> "{1..0}" have any more meaning than something like "{1..-1}"?)

Both have the same "quantity" of meaning :) I read {1..n} as a shorthand
for {i | 1 <= i and i <= n}, so both {1..0} and {1..-1} denote the empty
set. (OK, so the length of an empty set could be -1, but I do not think
this is what confuses people.)


> And it seems the length of tables with positive numeric keys that
> are not integers (e.g. { 'a', [1.5]='b', 'c' }) is not technically
> defined, either.

Yes.

-- Roberto