JS crota
JS crota

Reputation: 23

Lua - Size of table returning different

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.

Upvotes: 2

Views: 632

Answers (2)

Doug Currie
Doug Currie

Reputation: 41170

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.)

Upvotes: 3

Tyler
Tyler

Reputation: 55

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

Upvotes: 1

Related Questions