1
--tables for the 1st example
local table1EX1={1,2,3}
local table2EX1={4,5}
local temp={}

-- 1st example:
temp=table1EX1
for i=1,2 do
  temp[3+i]=table2EX1[i]
  print("#temp = "..#temp)
end

-- output from the print command:
-- #temp = 4
-- #temp = 5
-- this is what I intended to do but I need it to adapt to a changing table size

--tables for the 2nd example
local table1EX2={1,2,3}
local table2EX2={4,5}
local temp={}

-- 2nd example:
temp=table1EX2
for i=1,#table2EX2 do
  temp[#table1EX2+i]=table2EX2[i]
  print("#temp = "..#temp)
end

-- output from the print command:
-- #temp = 4
-- #temp = 6
-- this is what I tried and where I noticed something is wrong

#table_name only ever returns a single value and that's the numeric range from the first to the last entry within the named table.

Tests to confirm this: #1:

local tab={-1,0,_,nil,"a",nil,"x",_,3}
print(#tab) -- returns 9

#2:

local tab={1,2,3}
print(#tab) -- returns 3
tab[2]=nil
print(#tab) -- returns 3

#3:

local tab={1,2,3}
print(#tab) -- returns 3
tab[3]=nil
print(#tab) -- returns 2

I don't understand what's going wrong and why between example#1 and example#2: The code should work the same: table1EX1 and table1EX2 never receive any changes to their contents or size, because the temp variable is used to store the values in both cases. Yet in example#2 the code suddenly causes a change to the contents of table1, as can be seen by the print command output.

While the entire issue can be avoided by assigned variables, like...

--tables for the 2nd example
local table1EX2={1,2,3}
local table2EX2={4,5}
local temp={}

-- 2nd example:
temp=table1EX2
local x,y=#table2EX2,#table1EX2
for i=1,x do
  temp[y+i]=table2EX2[i]
  print("#temp = "..#temp)
end

...I'd like to understand what's wrong and why. Also what's the '#' properly called in English in this case ? Sharp, like in C# ? Lozenge, like the dictionary shows ?

  • Does this answer your question? [Why does Lua's length (#) operator return unexpected values?](https://stackoverflow.com/questions/23590885/why-does-luas-length-operator-return-unexpected-values) – Nifim Apr 05 '21 at 18:29
  • The `#` length operator is not defined for non-sequence tables, it should only be used when you know your table is a sequence otherwise results will be unpredictable. As for what we call `#` in english, it has many names `number sign`, `pound`, `hashtag`. I tend to favor number sign or if specifically lua i would call it length operator. – Nifim Apr 05 '21 at 18:31
  • The rule for the # operator in Lua is simple, as far as I can tell: it tells the length of a *table that is a sequence* if *it does not have any nil values*. Usage in any other situation is highly discouraged. – Real Apr 05 '21 at 22:23
  • (It does specify as well that, if there is a nil in a sequence, then it may return any number such that the next is nil. Please refrain from having nils in your sequence!) – Real Apr 05 '21 at 22:24

1 Answers1

2

Let's have a look what you're doing here. See comments

Exampe 1

local table1EX1={1,2,3} -- create a table with 3 elements
local table2EX1={4,5} -- create another table with 3 elements
local temp={} -- create an empty table

temp=table1EX1 -- temp now refers to table1EX1
-- in a loop append the 2 elements of table2EX1 to table2EX1 (or temp, same table)
for i=1,2 do
  temp[3+i]=table2EX1[i] -- first run temp[3+1], second temp[3+2]
  print("#temp = "..#temp)
end

Instead of

local temp = {}
temp = table1EX1

simply write

local temp = table1EX1

Example 2

local table1EX2={1,2,3} -- create a table with 3 elements
local table2EX2={4,5}  -- create a table with 2 elements
local temp={}  -- create an empty table

temp=table1EX2  -- temp now refers to table1EX2
-- in a loop from 1 to #table2EX2 (2)
for i=1,#table2EX2 do
  temp[#table1EX2+i]=table2EX2[i] -- first run temp[3+1], second temp[4+2]
  print("#temp = "..#temp)
end

You added 1 element to temp, so you added 1 element to table1EX2 because both refer to the same table. hence in the second loop cycle #table1EX2 is 4. That's the difference to example 1.

table values are copied by reference! local temp = table1EX1 does not copy any value from table1EX1 to temp. temp is just another reference to the table table1EX1 refers to.

local tab={-1,0,_,nil,"a",nil,"x",_,3}
print(#tab) -- returns 9

This is dangerous. Please refer to the Lua manual: https://www.lua.org/manual/5.4/manual.html#3.4.7

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

Only use the length operator if you know t is a sequence. That's a Lua table with integer indexes 1,..n without any gap.

Also what's the '#' properly called in English in this case ? Sharp, like in C#

It's the number sign or hash. In case of Lua it's called the length operator

Read this https://en.wikipedia.org/wiki/Number_sign

Piglet
  • 27,501
  • 3
  • 20
  • 43