2

guys. Someone can help me with this?

Input

a = {}

a.c = {1,2,3}

print(#a)

print(a.c)

Output

0

table: 0x11ed7a0

Why #a is 0? Why not 1?

Thanks.

JS crota
  • 23
  • 2
  • Possible duplicate of [Why does Lua's length (#) operator return unexpected values?](https://stackoverflow.com/questions/23590885/why-does-luas-length-operator-return-unexpected-values) – Tom Blodget Jan 26 '19 at 00:19

2 Answers2

3

It is zero because your table a is not a sequence.

A sequence is a table that uses keys from 1..n where n is the size of the sequence.

In other words, # is used for sequence length, not table length.

From the Lua 5.3 Reference Manual

A table with exactly one border is called a sequence. For instance, the table {10, 20, 30, 40, 50} is a sequence, as it has only one border (5). The table {10, 20, 30, nil, 50} has two borders (3 and 5), and therefore it is not a sequence. The table {nil, 20, 30, nil, nil, 60, nil} has three borders (0, 3, and 6), so it is not a sequence, too. The table {} is a sequence with border 0. Note that non-natural keys do not interfere with whether a table is a sequence.

When t is a sequence, #t returns its only border, which corresponds to the intuitive notion of the length of the sequence. When t is not a sequence, #t can return any of its borders. (The exact one depends on details of the internal representation of the table, which in turn can depend on how the table was populated and the memory addresses of its non-numeric keys.)

Doug Currie
  • 40,708
  • 1
  • 95
  • 119
1

Lua tables are a different kind of construct than those in other languages. As the Lua manual reads:

Tables are the main (in fact, the only) data structuring mechanism in Lua, and a powerful one. We use tables to represent ordinary arrays, symbol tables, sets, records, queues, and other data structures, in a simple, uniform, and efficient way.

In addition, a table is dynamic enough that you can use it in multiple ways at once. For example, a table could be used both as an array and a map at the same time. This has some unfortunate consequences internally. Internally, each Lua table has two parts: the array and hash map.

The length operator only operates on the array portion of the table; no extra memory is used to store the total number of items in the table including the hash map portion. If that functionality is desired, it must be manually implemented. A couple good ways to do so would be using getters and setters, manually updating a local counter, or using a proxy table with index and newindex metamethods.

As an interresting side note, it can sometimes become difficult to tell if a value is stored in the array or hash portions of the table. Consider these examples in Lua 5.3:

1: t = {true, nil, true}  -- #t = 3
2: t = {true, [2] = true} -- #t = 2
3: t = {true, [3] = true} -- #t = 1
4: t = {true, true, true} t[2] = nil -- #t = 3
Tyler
  • 55
  • 5
  • A minor quibble, though I might be misunderstanding you: the length operator does take into account integer keys in the hash part of the table. For instance, in Lua 5.3 `t = {1, 2, nil, 4} t[5] = 5` creates a 4-entry array part containing the keys `1`, `2`, `4` and one-entry hash part containing the key `5` (I checked with the latest version of [lua-getsize](https://github.com/siffiejoe/lua-getsize) from Github), but `#t` is `5` rather than `4`. – cyclaminist Jan 24 '19 at 00:32
  • The example you gave, `t = {1, 2, nil, 4}` creates an array internally of size 8 and fills locations 1, 2, and 3 (represented as 0, 1, and 2 internally) with numbers. It then adds a fifth element to it, which also fits into the array. This makes the size of the array 5. – Tyler Jan 24 '19 at 06:05
  • Another interesting note is that only the array size is stored, not the number of elements in the array. When luaH_getn is called, it does a binary search starting at the array end for nils to determine the length, making `t = {true, true, true, true} t[8] = true` return an length of 8. Some interesting other cases due to this binary search are `t = {true, true, true, true} t[6] = true` --> length 6, and `t = {true, true, true, true} t[7] = true` --> length 4. In short, length on sparse arrays is undefined. – Tyler Jan 24 '19 at 06:12