1
votes

I'm a beginner in Lua.

I thought pushing values to a table using string keys would automatically also do number indexing but I think I was wrong about this.

My Code :

local t = {}
t.name = "John"
t.age = 30
print("Name : " .. t.name .. "\nAge : " .. t.age)

While this code works fine and prints the expected result,

Name : John
Age : 30

If I try to print the result this way,

print("Name : " .. t[1] .. "\nAge : " .. t[2])

I get the following error:

lua: main.lua:5: attempt to concatenate a nil value (field '?')
stack traceback:
    main.lua:5: in main chunk
    [C]: in ?

Does this mean I cannot iterate through the table using for with number indexing without having to know the key strings?

If so, is there any work around to make the both way work?

2
Your table is effectively local t = { ["name"] = "John", ["age"] = 30 } as you can see the keys [1] and [2] are not present. It is also not possible to add number indexing because if the keys in a table aren't numbers, the order is unspecified. You don't need number indices to iterate a table with for. Just try for k,v in pairs(t) do print(k,v) end.Henri Menke

2 Answers

2
votes

Adding values to a table does not also add them as with index keys as well. When you go to use the values in your table you can access them either using the dot notation, as in your first example, or like this:

print("Name : " .. t["name"] .. "\nAge : " .. t["age"])

You can iterate over the key value pairs in the table using the function pairs like so:

for k, v in pairs(t) do
    print(k, v)
end

If you want to use indexes instead of strings keys, you can set it up like this:

local t = {
    "John",
    30,
}
print("Name : " .. t[1].. "\nAge : " .. t[2])

When you do it this way, the values in the table t have integer indexes automatically assigned to each value. If you want to iterate over them one by one, you can iterate with ipairs:

for i, v in ipairs(t) do
    print(i, v)
end
1
votes

You can hack yourself a numeric index using a metatable, but the that will be completely useless because in a table with non-numeric, non-consecutive indices the order is unspecified.

local mt = { __index = function(t, n)
                 assert(n > 0)
                 for k, v in pairs(t) do
                     n = n - 1
                     if n == 0 then
                         return v
                     end
                 end
           end }

local t = {}
setmetatable(t, mt)
t.name = "John"
t.age = 30
print("Name : " .. t.name .. "\nAge : " .. t.age)
print("Name : " .. t[1] .. "\nAge : " .. t[2])

Executing the above script several times in a row will reveal the problem:

$ lua test.lua 
Name : John
Age : 30
Name : John
Age : 30
$ lua test.lua 
Name : John
Age : 30
Name : 30
Age : John