tables

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

tables

D Burgess-4
I thought I understodd Lua tables, but obviously not.
Would someone explain the rules that cover the following
(5.1) behaviour  of '#':

> a={nil,2,3,4,5,6}
> =#a
6

> a={1,2,3,4,5,6}
> =#a
6
> a[1]=nil
> =#a
6

> a={[2]=2, [3]=3}
> =#a
0
> a[1]=1
> =#a
3
> a[1]=nil
> =#a
3

David B.


Reply | Threaded
Open this post in threaded view
|

Re: tables

Chris-41
On 3/5/06, D Burgess <[hidden email]> wrote:
I thought I understodd Lua tables, but obviously not.
Would someone explain the rules that cover the following
(5.1) behaviour  of '#':

> a={nil,2,3,4,5,6}
> =#a
6

What I find interesting is that an explicitly set nil value is not considered a "hole" in the table.

According to the documentation that shouldn't be.  A bug?

--
// Chris
Reply | Threaded
Open this post in threaded view
|

Re: tables

Chris-41


What I find interesting is that an explicitly set nil value is not considered a "hole" in the table.

According to the documentation that shouldn't be.  A bug?

By the way, I find the documentation wording very confusing:

The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t[1] is nil, n ***may*** be zero. For a regular array, with non-nil values from 1 to a given n, its length is exactly that n, the index of its last value. If the array has "holes" (that is, nil values between other non-nil values), then #t ***may*** be any of the indices that directly precedes a nil value (that is, it ***may*** consider any such nil value as the end of the array).

It _might_ consider a nil the end?  Well, does it or does it not?  And if it can change I think that needs to be made clear.

--
// Chris
Reply | Threaded
Open this post in threaded view
|

Re: tables

D Burgess-4
It would seem that we have the "never assigned nil" and
the "assigned nil".

David B

On 3/6/06, Chris <[hidden email]> wrote:
>
>
>
> >
> >
> >
> > What I find interesting is that an explicitly set nil value is not
> considered a "hole" in the table.
> >
> > According to the documentation that shouldn't be.  A bug?
>
>
>  By the way, I find the documentation wording very confusing:
>
>  The length of a table t is defined to be any integer index n such that t[n]
> is not nil and t[n+1] is nil; moreover, if t[1] is nil, n ***may*** be zero.
> For a regular array, with non-nil values from 1 to a given n, its length is
> exactly that n, the index of its last value. If the array has "holes" (that
> is, nil values between other non-nil values), then #t ***may*** be any of
> the indices that directly precedes a nil value (that is, it ***may***
> consider any such nil value as the end of the array).
>  It _might_ consider a nil the end?  Well, does it or does it not?  And if
> it can change I think that needs to be made clear.
>
>  --
>  // Chris
>


Reply | Threaded
Open this post in threaded view
|

RE: tables

Dolan, Ryanne Thomas (UMR-Student)
The length operator only guarantees a predictable result in the case of an "array" without holes, like: {1, 2, 3, 4, 5}.  If there are any holes at all, then you can't rely on the # operator to give you the result you expect.  This is why the manual is a bit confusing; it gives a definition that is always valid, but not really useful except in the special case of an array without holes.

So, your experiment with {nil, 2, 3, 4, 5} gives you a valid result (according to the manual's definition) but it isn't a useful value.  This is not a bug at all, but an optimization.

-----Original Message-----
From: [hidden email] on behalf of D Burgess
Sent: Sun 3/5/2006 5:05 PM
To: Lua list
Subject: Re: tables
 
It would seem that we have the "never assigned nil" and
the "assigned nil".

David B

On 3/6/06, Chris <[hidden email]> wrote:
>
>
>
> >
> >
> >
> > What I find interesting is that an explicitly set nil value is not
> considered a "hole" in the table.
> >
> > According to the documentation that shouldn't be.  A bug?
>
>
>  By the way, I find the documentation wording very confusing:
>
>  The length of a table t is defined to be any integer index n such that t[n]
> is not nil and t[n+1] is nil; moreover, if t[1] is nil, n ***may*** be zero.
> For a regular array, with non-nil values from 1 to a given n, its length is
> exactly that n, the index of its last value. If the array has "holes" (that
> is, nil values between other non-nil values), then #t ***may*** be any of
> the indices that directly precedes a nil value (that is, it ***may***
> consider any such nil value as the end of the array).
>  It _might_ consider a nil the end?  Well, does it or does it not?  And if
> it can change I think that needs to be made clear.
>
>  --
>  // Chris
>


<<winmail.dat>>

Reply | Threaded
Open this post in threaded view
|

Re: tables

D Burgess-4
I think the behaviour is  dangerous.

> =#{nil,2}
2
> =#{[2]=2}
0

The behaviour changes depending on the syntax of construction.

David B

On 3/6/06, Dolan, Ryanne Thomas (UMR-Student) <[hidden email]> wrote:
>
> The length operator only guarantees a predictable result in the case of an "array" without holes, like: {1, 2, 3, 4, 5}.  If there are any holes at all, then you can't rely on the # operator to give you the result you expect.  This is why the manual is a bit confusing; it gives a definition that is always valid, but not really useful except in the special case of an array without holes.
>
> So, your experiment with {nil, 2, 3, 4, 5} gives you a valid result (according to the manual's definition) but it isn't a useful value.  This is not a bug at all, but an optimization.
>


Reply | Threaded
Open this post in threaded view
|

Re: tables

Adam D. Moss
In reply to this post by Chris-41

It _might_ consider a nil the end? Well, does it or does it not? And if it can change I think that needs to be made clear.

It might.  It depends on some magical implementation stuff.
I don't think it can be any clearer.  :)

--adam

Reply | Threaded
Open this post in threaded view
|

RE: tables

Dolan, Ryanne Thomas (UMR-Student)
In reply to this post by D Burgess-4
This behaviour is not dangerous; it is expected.  What is dangerous is trying to use the result of the length operator on an array with holes.

In other words, you should never try #{nil, 2} or #{[2] = 2} in the first place.  If you do, you must expect an unpredictable result.

Furthermore, you cannot expect #{nil, 2} to always return 2, nor #{[2] = 2} to return 0.  As I said earlier, the length operator only gaurantees a predictable result with arrays with no holes, so later versions of the interpretter could have #{nil, 2} return 0 and #{[2] = 2} return 2.  According to the definition of the length operator, both 0 and 2 are valid lengths of {nil, 2} and {[2] = 2}.



-----Original Message-----
From: [hidden email] on behalf of D Burgess
Sent: Sun 3/5/2006 5:39 PM
To: Lua list
Subject: Re: tables
 
I think the behaviour is  dangerous.

> =#{nil,2}
2
> =#{[2]=2}
0

The behaviour changes depending on the syntax of construction.

David B

On 3/6/06, Dolan, Ryanne Thomas (UMR-Student) <[hidden email]> wrote:
>
> The length operator only guarantees a predictable result in the case of an "array" without holes, like: {1, 2, 3, 4, 5}.  If there are any holes at all, then you can't rely on the # operator to give you the result you expect.  This is why the manual is a bit confusing; it gives a definition that is always valid, but not really useful except in the special case of an array without holes.
>
> So, your experiment with {nil, 2, 3, 4, 5} gives you a valid result (according to the manual's definition) but it isn't a useful value.  This is not a bug at all, but an optimization.
>


<<winmail.dat>>

Reply | Threaded
Open this post in threaded view
|

Re: tables

David Given
In reply to this post by D Burgess-4
On Sunday 05 March 2006 23:39, D Burgess wrote:
> I think the behaviour is  dangerous.
>
> > =#{nil,2}

Unexpected, yes, but you are *not allowed* to put nils into an array and 
expect it to work as an array --- as soon as you do so, you stop being able 
to reliably use the array operators and have to use the fully-fledged table 
operators instead.

I wonder if it would be possible to have a debug option that could check for 
this kind of thing? So that, say, tables with an empty hash part and a 
non-empty array part produced a diagnostic if you tried to write a nil into 
them? It would make it a little more obvious what was going on.

-- 
+- David Given --McQ-+ 
|  [hidden email]    | Uglúk u bagronk sha pushdug Internet-glob bbhosh
| ([hidden email]) | skai.
+- www.cowlark.com --+ 

Attachment: pgp_zucdWG9vA.pgp
Description: PGP signature

Reply | Threaded
Open this post in threaded view
|

Re: tables

Chris-41
In reply to this post by Dolan, Ryanne Thomas (UMR-Student)
On 3/5/06, Dolan, Ryanne Thomas (UMR-Student) <[hidden email]> wrote:

This behaviour is not dangerous; it is expected.  What is dangerous is trying to use the result of the length operator on an array with holes.

In other words, you should never try #{nil, 2} or #{[2] = 2} in the first place.  If you do, you must expect an unpredictable result.

Furthermore, you cannot expect #{nil, 2} to always return 2, nor #{[2] = 2} to return 0.  As I said earlier, the length operator only gaurantees a predictable result with arrays with no holes, so later versions of the interpretter could have #{nil, 2} return 0 and #{[2] = 2} return 2.  According to the definition of the length operator, both 0 and 2 are valid lengths of {nil, 2} and {[2] = 2}.

Can someone define what a "hole" in an array is?  Why can't I have an array with nil values in it?  The current behaviour suggests those are not holes.  However, the documentation gives a vague explaination that says nils *might* be "holes".  But again, judging by the actual behaviour, setting a particular entry in an array to nil is not considered a hole.   I think that's probably a good thing because it allows me to build an array and set some values to nil as a placeholder.

However, if a change in implementation could change this behaviour that makes me feel uneasy.  This whole issue makes me realize that Lua really needs an official well defined language specification to be taken seriously.

--
// Chris
Reply | Threaded
Open this post in threaded view
|

Re: tables

D Burgess-4
In reply to this post by Dolan, Ryanne Thomas (UMR-Student)
How about -

> a={1,2,3,4,5,6}
> a[1]=nil
> =#a
6

Surely, one would *expect* # to return the same number as the
number of iterations produced by ipairs() ?

David B.


 Ryanne Thomas (UMR-Student) wrote:
> In other words, you should never try #{nil, 2} or #{[2] = 2} in the first place.  If you do, you must expect an unpredictable result.


Reply | Threaded
Open this post in threaded view
|

Re: tables

Alex Queiroz
In reply to this post by Chris-41
Hallo,

On 3/5/06, Chris <[hidden email]> wrote:
>
>  However, if a change in implementation could change this behaviour that
> makes me feel uneasy.  This whole issue makes me realize that Lua really
> needs an official well defined language specification to be taken seriously.
>

     What you must really realize is that you didn't understand the
documentation. It could have read "The behaviour of # is undefined if
there are holes in the array". But instead it tried to explain what
that undefined behaviour would look like, and that confused you.
     So, to make things clearer, don't use # if you have holes (nils)
in the array. Period.

--
-alex
http://www.ventonegro.org/


Reply | Threaded
Open this post in threaded view
|

Re: tables

Adam D. Moss
In reply to this post by Chris-41
Chris wrote:
Can someone define what a "hole" in an array is?

nil(s) in an otherwise contiguous run 1..n

> Why can't I have an array with nil values in it?

you can, but the table length operator on such an array
is defined as in the manual.

> But again, judging by the actual
behaviour, setting a particular entry in an array to nil is not considered a hole.

No, it's a hole.  It simply may or may not affect the length
operator, as documented, resulting in a length that you may or
may not expect.

However, if a change in implementation could change this behaviour that makes me feel uneasy.

The length operator works as documented, and presumably a change
in implementation would also work as documented.  You should ask
yourself what the expected behaviour would be given an array
with holes (count up to the first nil?  count up to the last
non-nil?  something else?).  For efficiency Lua's length operator
only gives a unambiguous answer in the absence of holes, and
is possibly over-wordily documented as such; if you utterly
require a specific policy in the presence of holes you can
implement it easily enough.

> This whole issue makes me realize that Lua really
needs an official well defined language specification to be taken seriously.

I take Lua pretty seriously!

--adam

Reply | Threaded
Open this post in threaded view
|

Re: tables

Chris-41
In reply to this post by Alex Queiroz
On 3/5/06, Alex Queiroz <[hidden email]> wrote:
     What you must really realize is that you didn't understand the
documentation. It could have read "The behaviour of # is undefined if
there are holes in the array". But instead it tried to explain what
that undefined behaviour would look like, and that confused you.
     So, to make things clearer, don't use # if you have holes (nils)
in the array. Period.

No, I understand the documentation.  It's just vague and the implementation is loose.

Now, the thing is, I don't really care one way or the other because I don't expect Lua to be standardized like C or something so I just accept it as it is, warts and all.  It works well enough.   I probably shouldn't have gotten involved in this conversation in the first place.  :)

--
// Chris
Reply | Threaded
Open this post in threaded view
|

Re: tables

Klaus Ripke
On Sun, Mar 05, 2006 at 07:29:27PM -0500, Chris wrote:
>    Now, the thing is, I don't really care one way or the other because I
>    don't expect Lua to be standardized like C or something so I just accept
>    it as it is, warts and all.  It works well enough.   I probably shouldn't
>    have gotten involved in this conversation in the first place.  :)
standardized like C? you do not want this! getting numbers ...

$ grep -ic implementation-defined C?9        
C89:127
C99:142
$ grep -ic undefined C?9
C89:108
C99:181
... so apparently it even got worse?


I reckon Lua makes bella figura here.


saludos

Reply | Threaded
Open this post in threaded view
|

Re: tables

Alex Queiroz
In reply to this post by Chris-41
Hallo,

On 3/5/06, Chris <[hidden email]> wrote:
>
>  Now, the thing is, I don't really care one way or the other because I don't
> expect Lua to be standardized like C or something so I just accept it as it
> is, warts and all.  It works well enough.   I probably shouldn't have gotten
> involved in this conversation in the first place.  :)
>

     Alas, if standards could eliminate warts...

--
-alex
http://www.ventonegro.org/


Reply | Threaded
Open this post in threaded view
|

Re: tables

D Burgess-4
In reply to this post by Chris-41
Chris  wrote:
> [...] I probably shouldn't have gotten
> involved in this conversation in the first place.  :)

Lots of passionate responses.
I initially asked a question. Thanks for the replies.
Having reviewed a few historical list mails, I should point out
that one of the reasons for # was to provide a syntactically
cheap way of table (array) appends, the example provided by
Luiz was:

t[#t +1] = newvalue


So that arrays do not have to be reconstructed and so that we
dont have to use (next(t)) == 1 as test for emptiness, it would
be convenient (and consistent) if the # operator provided the
following behaviour (this is the assertion):

"# provides the same number as the number of iterations
provided by ipairs".
e.g.

n=0 ; for i,v in ipairs(t) do n=n+1 end

and

n = #t

"should" provide the same result

which means that

for i,v in ipairs(t) do

and

for i = 1, #t  do

would provide the same number of iterations.

This IMHO would provide an improvement in the behaviour of
the language and a simplification of the doco. I would not be too
fussed if the rule allowed for arrays to be iterated starting at
numbers > 1. This argument is about # and ipairs consistency.

I note with some interest that the deprecated table.foreachi()
provides the consistency that ipairs() does not.

David B.


Reply | Threaded
Open this post in threaded view
|

RE: tables

Couwenberg, Wim
In reply to this post by D Burgess-4
> it 
> would be convenient (and consistent) if the # operator 
> provided the following behaviour (this is the assertion):
> 
> "# provides the same number as the number of iterations 
> provided by ipairs".

Convenient maybe, but also more expensive.  The current # implementation
is O(log(N)) where N is the number of entries in the array part.  The
rule above would make that O(N) in general.  You can use table.maxn to
find the highest overall numerical index (ignoring gaps).  This is of
course also more expensive than applying #.

--
Wim

This message and attachment(s) are intended solely for the use of the addressee and may contain information that is privileged, confidential or otherwise exempt from disclosure under applicable law.  
If you are not the intended recipient or agent thereof responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited.  
If you have received this communication in error, please notify the sender immediately by telephone and with a "reply" message.  
Thank you for your cooperation.




Reply | Threaded
Open this post in threaded view
|

Re[2]: tables

Gunnar Zötl
>> it 
>> would be convenient (and consistent) if the # operator 
>> provided the following behaviour (this is the assertion):
>> 
>> "# provides the same number as the number of iterations 
>> provided by ipairs".

CW> Convenient maybe, but also more expensive.  The current # implementation
CW> is O(log(N)) where N is the number of entries in the array part.  The

plus, it would change the semantics of the # operator such that the
expression t[#t+1]==nil would not necessarily be true any more.

Gunnar




Reply | Threaded
Open this post in threaded view
|

Re: tables

Wim Couwenberg-2
>>> it
>>> would be convenient (and consistent) if the # operator 
>>> provided the following behaviour (this is the assertion):
>>> 
>>> "# provides the same number as the number of iterations 
>>> provided by ipairs".

CW>> Convenient maybe, but also more expensive.  The current # implementation
CW>> is O(log(N)) where N is the number of entries in the array part.  The

> plus, it would change the semantics of the # operator such that the
> expression t[#t+1]==nil would not necessarily be true any more.

That would still be true.  (ipairs stops at the first nil value.)

--
Wim



12