Why does #{nil, "sun"} output 2, whereas a={}; a[2]="sun"; print(#a) output 0?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Why does #{nil, "sun"} output 2, whereas a={}; a[2]="sun"; print(#a) output 0?

孙世龙 sunshilong
Hi, list

Here are the first code snippet and the output:
>a={nil, "sun"}    --output: 2

Here are the second code snippet and the output:
>b = {}
>b[2] = "sun"
>print(#b)          --output:0

Here are the third code snippet and the output:

> function printTab(tab)
>> for k,v in pairs(tab) do
>> print(k,v)
>> end
>> end
>
>type(a) == type(b)    --output:true
>a == b                      --output: false     amazing!!!
>> printTab(a)            --output: 2       sun
>> printTab(b)             --output: 2       sun


It's amazing that "printTab(a)" and "printTab(b)" are the same whereas
"#a" and "#b" are different (and "a == b" outputs false).
Could somebody shed some light on this question?

Best regards
Sunshilong
Reply | Threaded
Open this post in threaded view
|

Re: Why does #{nil, "sun"} output 2, whereas a={}; a[2]="sun"; print(#a) output 0?

孙世龙 sunshilong
Sorry, hit send too early. Was going to say here:
> a[1] == b[1]   --output: true
> a[2] == b[2]   --output: true
> a == b           --output: false    amazing!!!
It's amazing that both "a[1]==b[1]" and "a[2]==b[2]" return "true" whereas
"a==b" returns "false".

Best regards
Sunshilong

On Mon, Oct 12, 2020 at 2:38 PM 孙世龙 sunshilong <[hidden email]> wrote:

>
> Hi, list
>
> Here are the first code snippet and the output:
> >a={nil, "sun"}    --output: 2
>
> Here are the second code snippet and the output:
> >b = {}
> >b[2] = "sun"
> >print(#b)          --output:0
>
> Here are the third code snippet and the output:
> > function printTab(tab)
> >> for k,v in pairs(tab) do
> >> print(k,v)
> >> end
> >> end
> >
> >type(a) == type(b)    --output:true
> >a == b                      --output: false     amazing!!!
> >> printTab(a)            --output: 2       sun
> >> printTab(b)             --output: 2       sun
>
>
> It's amazing that "printTab(a)" and "printTab(b)" are the same whereas
> "#a" and "#b" are different (and "a == b" outputs false).
> Could somebody shed some light on this question?
>
> Best regards
> Sunshilong
Reply | Threaded
Open this post in threaded view
|

Re: Why does #{nil, "sun"} output 2, whereas a={}; a[2]="sun"; print(#a) output 0?

Francisco Olarte
In reply to this post by 孙世龙 sunshilong
On Mon, Oct 12, 2020 at 8:39 AM 孙世龙 sunshilong <[hidden email]> wrote:

>
> Hi, list
>
> Here are the first code snippet and the output:
> >a={nil, "sun"}    --output: 2
>
> Here are the second code snippet and the output:
> >b = {}
> >b[2] = "sun"
> >print(#b)          --output:0
>
> Here are the third code snippet and the output:
> > function printTab(tab)
> >> for k,v in pairs(tab) do
> >> print(k,v)
> >> end
> >> end
> >
> >type(a) == type(b)    --output:true
> >a == b                      --output: false     amazing!!!
> >> printTab(a)            --output: 2       sun
> >> printTab(b)             --output: 2       sun
>
>
> It's amazing that "printTab(a)" and "printTab(b)" are the same whereas
> "#a" and "#b" are different (and "a == b" outputs false).
> Could somebody shed some light on this question?

# works as sequence length only when you have "normal", sequence,
i.e., without embedded nil. In fact it is a border  finding opertator,
defined in the manual as
"The length operator applied on a table returns a border in that
table. A border in a table t is any natural number that satisfies the
following condition:
     (border == 0 or t[border] ~= nil) and t[border + 1] == nil
In words, a border is any (natural) index present in the table that is
followed by an absent index (or zero, when index 1 is absent)."

Probably when you use the {} construct lua builds a table with two
elements in the array part, but when you build b it gets 0 elements in
the array part. Lua is allowed by the definition to do the following (
it may be doing other things ).
- For a: two elements in array part. Array length is 2. a[2] is not
nil. a[3] is nil. return 2.
- For b: Empty array part. b[1] is nil. Return 0.

Tables in lua are initially easy, but complex beasts when doing some
list oriented things. This arises from the fact that they are really
dictionaries ( associative arrays ) with some optimizations and
niceties to treat them as lists, and from the fact that nil is special
in lua. It is a legal value for a local variable, but you cannot store
it in a table because assigning nil is used to delete elements (
unlike, i.,e., perl, or Java, or python , where key existence is
separated and you have a method for deleting entries ).

Francisco Olarte.
Reply | Threaded
Open this post in threaded view
|

Re: Why does #{nil, "sun"} output 2, whereas a={}; a[2]="sun"; print(#a) output 0?

Robert Burke
In reply to this post by 孙世龙 sunshilong
On Mon, Oct 12, 2020 at 3:48 PM 孙世龙 sunshilong <[hidden email]> wrote:

>
> Sorry, hit send too early. Was going to say here:
> > a[1] == b[1]   --output: true
> > a[2] == b[2]   --output: true
> > a == b           --output: false    amazing!!!
> It's amazing that both "a[1]==b[1]" and "a[2]==b[2]" return "true" whereas
> "a==b" returns "false".
>
> Best regards
> Sunshilong

For tables, == will just tell you whether a and b are the same table,
not whether they have equal contents. That's like python's "is",
Java's "==", and JavaScript's "===".
Reply | Threaded
Open this post in threaded view
|

Re: Why does #{nil, "sun"} output 2, whereas a={}; a[2]="sun"; print(#a) output 0?

Viacheslav Usov
On Mon, Oct 12, 2020 at 10:23 AM Robert Burke <[hidden email]> wrote:

> For tables, == will just tell you whether a and b are the same table

... when no __eq metamethod is defined. See the manual for a full specification.

Cheers,
V.
Reply | Threaded
Open this post in threaded view
|

Re: Why does #{nil, "sun"} output 2, whereas a={}; a[2]="sun"; print(#a) output 0?

孙世龙 sunshilong
In reply to this post by Francisco Olarte
>Probably when you use the {} construct lua builds a table with two
>elements in the array part, but when you build b it gets 0 elements in
>the array part. Lua is allowed by the definition to do the following (
>it may be doing other things ).
>- For a: two elements in array part. Array length is 2. a[2] is not
>nil. a[3] is nil. return 2.
>- For b: Empty array part. b[1] is nil. Return 0.
a[1] is nil, too.
And both "a[1]==b[1]" and "a[2]==b[2]" return "true".

On Mon, Oct 12, 2020 at 3:57 PM Francisco Olarte <[hidden email]> wrote:

>
> On Mon, Oct 12, 2020 at 8:39 AM 孙世龙 sunshilong <[hidden email]> wrote:
> >
> > Hi, list
> >
> > Here are the first code snippet and the output:
> > >a={nil, "sun"}    --output: 2
> >
> > Here are the second code snippet and the output:
> > >b = {}
> > >b[2] = "sun"
> > >print(#b)          --output:0
> >
> > Here are the third code snippet and the output:
> > > function printTab(tab)
> > >> for k,v in pairs(tab) do
> > >> print(k,v)
> > >> end
> > >> end
> > >
> > >type(a) == type(b)    --output:true
> > >a == b                      --output: false     amazing!!!
> > >> printTab(a)            --output: 2       sun
> > >> printTab(b)             --output: 2       sun
> >
> >
> > It's amazing that "printTab(a)" and "printTab(b)" are the same whereas
> > "#a" and "#b" are different (and "a == b" outputs false).
> > Could somebody shed some light on this question?
>
> # works as sequence length only when you have "normal", sequence,
> i.e., without embedded nil. In fact it is a border  finding opertator,
> defined in the manual as
> "The length operator applied on a table returns a border in that
> table. A border in a table t is any natural number that satisfies the
> following condition:
>      (border == 0 or t[border] ~= nil) and t[border + 1] == nil
> In words, a border is any (natural) index present in the table that is
> followed by an absent index (or zero, when index 1 is absent)."
>
> Probably when you use the {} construct lua builds a table with two
> elements in the array part, but when you build b it gets 0 elements in
> the array part. Lua is allowed by the definition to do the following (
> it may be doing other things ).
> - For a: two elements in array part. Array length is 2. a[2] is not
> nil. a[3] is nil. return 2.
> - For b: Empty array part. b[1] is nil. Return 0.
>
> Tables in lua are initially easy, but complex beasts when doing some
> list oriented things. This arises from the fact that they are really
> dictionaries ( associative arrays ) with some optimizations and
> niceties to treat them as lists, and from the fact that nil is special
> in lua. It is a legal value for a local variable, but you cannot store
> it in a table because assigning nil is used to delete elements (
> unlike, i.,e., perl, or Java, or python , where key existence is
> separated and you have a method for deleting entries ).
>
> Francisco Olarte.
Reply | Threaded
Open this post in threaded view
|

Re: Why does #{nil, "sun"} output 2, whereas a={}; a[2]="sun"; print(#a) output 0?

Philippe Verdy-2
In reply to this post by 孙世龙 sunshilong
What you have really done is two create two separate tables; even if these tables have the same keys and values, they are still distinct (and their keys can be set separately). Setting any key on a table does not change its reference. When you write 'a==b' you don't test if their content are equal, you just test if they are references to the same table: '==' is not a "deep" equality test. Remember that tables are used in Lua to act as "objects"; their content is exactly like an unordered set of properties, indexed by a unique key. Technically these objects do not even have a welldefined "length" (this is the main difference with arrays/vectors, that Lua represent as tables whose keys form a sequence, but sequences in Lua are not restricted to be just tables, they could be "generators" as well, accessed... sequentially with a well defined order of integer keys starting from 1 but possibility no end, where as a table in Lua can be accessed in random order on specific keys. Tables do not necessarily store their content in memory, because they can have a metatable containing accessor methods.

For this case, Lua behaves like other similar languages: Javascript, Python, Postscript, C#, PHP, ...

Le lun. 12 oct. 2020 à 08:48, 孙世龙 sunshilong <[hidden email]> a écrit :
Sorry, hit send too early. Was going to say here:
> a[1] == b[1]   --output: true
> a[2] == b[2]   --output: true
> a == b           --output: false    amazing!!!
It's amazing that both "a[1]==b[1]" and "a[2]==b[2]" return "true" whereas
"a==b" returns "false".

Best regards
Sunshilong

On Mon, Oct 12, 2020 at 2:38 PM 孙世龙 sunshilong <[hidden email]> wrote:
>
> Hi, list
>
> Here are the first code snippet and the output:
> >a={nil, "sun"}    --output: 2
>
> Here are the second code snippet and the output:
> >b = {}
> >b[2] = "sun"
> >print(#b)          --output:0
>
> Here are the third code snippet and the output:
> > function printTab(tab)
> >> for k,v in pairs(tab) do
> >> print(k,v)
> >> end
> >> end
> >
> >type(a) == type(b)    --output:true
> >a == b                      --output: false     amazing!!!
> >> printTab(a)            --output: 2       sun
> >> printTab(b)             --output: 2       sun
>
>
> It's amazing that "printTab(a)" and "printTab(b)" are the same whereas
> "#a" and "#b" are different (and "a == b" outputs false).
> Could somebody shed some light on this question?
>
> Best regards
> Sunshilong