Lua table examples are not working for me

121 Views Asked by At

I'm trying code from lua.org and from my 4th edition Programming in Lua hardcopy, and as far as I've read all these table examples should work but 3 out of 4 don't, and I cant find anything the docs that says why. Some help on what I am missing appreciated. I assume some spec has changed as I already found out with table.getn() not being available anymore. My linux box has Lua 5.3.5

local t1={}
t1[1]="Foo"
t1[2]="Bar"
print("Size: "..#t1)
print("Works:"..table.concat(t1,'$$'))

local t2={}
t2[5]="Foo"
t2[40]="Bar"
print("Size: "..#t2)
print("Doesnt Work:"..table.concat(t2,'$$'))

local t3={}
t3["A"]="Foo"
t3["B"]="Bar"
print("Size: "..#t3)
print("Doesnt Work:"..table.concat(t3,'$$'))

local t4={}
t4.A="Foo"
t4.B="Bar"
print("Size: "..#t4)
print("Doesnt Work:"..table.concat(t4,'$$'))

Results

Size: 2
Works:Foo$$Bar
Size: 0
Doesnt Work:
Size: 0
Doesnt Work:
Size: 0
Doesnt Work:
1

There are 1 best solutions below

0
On

Please read Lua Reference Manual: 3.4.7 The Length Operator

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

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 nil at index 4 is called a hole.) The table {nil, 20, 30, nil, nil, 60, nil} has three borders (0, 3, and 6) and three holes (at indices 1, 4, and 5), 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.)

Applied to your examples:

local t1={}
t1[1]="Foo"
t1[2]="Bar"

t1 has only one boarder (2), because t1[2] ~= nil and t1[2+1] == nil.

t1 has only 1 border -> t1 is a squence -> #t1 is the length of t1.

local t2={}
t2[5]="Foo"
t2[40]="Bar"

t2 has 3 borders (0, 5, 40), because boarder == 0 and t[0+1] == nil, t[5] ~= nil and t[5+1] == nil, t[40]~=nil and t[40+1]==nil

t2 has more than one borders-> #t2 is any of its borders, not its length.

local t3={}
t3["A"]="Foo"
t3["B"]="Bar"

t3 has 1 border (0), because border == 0 and t3[0+1] == nil, no more numeric keys so no more borders. t3 has only one border -> t3 is a sequence with length 0.

local t4={}
t4.A="Foo"
t4.B="Bar"

is the same as t4 as t.name is syntactic sugar for t["name"]. Only works for valid Lua names!

t1 is the only sequence among your examples and hence the only one # yields the number of element for.

If you are unsure if you have a sequence you should count the elements like so:

local n = 0
for _ in pairs(t) do
  n = n + 1
end

This is how you would print the boarders of a table t:

function printBorders(t)
  local borders = {}
  for k in pairs(t) do
    if  type(k) == "number" and
      t[k] ~= nil and t[k+1] == nil then
      table.insert(borders, k)
    end
  end
  if t[1] == nil then table.insert(borders, 0) end
  table.sort(borders)
  print(table.concat(borders, ", "))
end