Step 1 of 5 · Reading · ~3 min
Learn
Tables — The One Data Structure
Tables as Arrays
Lua has exactly one container type: the table. No separate array, list, dictionary, set, queue or object — a table is an associative map from keys to values, and when its keys happen to be the integers 1, 2, 3 and so on, it behaves as an array. Every other data structure you will ever build in Lua is a table wearing a costume.
One is the first index
Lua counts from 1, and the whole standard library agrees: #, ipairs, table.insert, table.remove, table.concat and table.sort all assume the first element lives at index 1.
local fruits = {"apple", "banana", "cherry"}
print(fruits[1])
print(fruits[3])
print(#fruits)
--> apple
--> cherry
--> 3
fruits = {"apple", "banana", "cherry"}
key 1 2 3
value "apple" "banana" "cherry"
^
first element — there is no fruits[0]
Reading fruits[0] is not an error. It returns nil, quietly, exactly like any other absent key. That is why a 0-based habit shows up as an arithmetic-on-nil error two lines later instead of as an out-of-bounds message.
Growing and shrinking
local q = {"a", "b", "c"}
table.insert(q, "d")
table.insert(q, 1, "z")
print(table.concat(q, ","))
table.remove(q, 1)
print(table.concat(q, ","))
print(#q)
--> z,a,b,c,d
--> a,b,c,d
--> 4
table.insert(t, v) appends. table.insert(t, pos, v) inserts at pos and shifts everything above it up. table.remove(t, pos) deletes at pos, shifts everything down to close the gap, and returns the value it removed. Writing t[#t + 1] = v appends just as well and is a common sight in real code.
Walking the array
ipairs yields index and value starting at 1, and stops at the first missing index.
local scores = {10, 20, 30}
for i, v in ipairs(scores) do
print(i .. ":" .. v)
end
--> 1:10
--> 2:20
--> 3:30
When you only care about the values, the convention is to name the index _.
local total = 0
for _, v in ipairs(scores) do
total = total + v
end
print(total)
--> 60
What a hole does to a table
Assigning nil does not blank a slot — it removes the key entirely. The table now has a hole, and both # and ipairs stop promising what you want.
local t = {10, 20, 30}
t[2] = nil
for i, v in ipairs(t) do
print(i .. ":" .. v)
end
--> 1:10
t[3] still exists and still holds 30; ipairs simply refuses to step across the gap. #t is murkier still: the manual defines it as a border of the table, and a table with a hole has more than one valid border, so #t may legitimately answer 1 or 3 here. Do not build anything on that answer.
✓ keep sequences dense — delete with table.remove, which closes the gap
✗ t[i] = nil in the middle of a list you still intend to iterate or measure
Tables are references
A table variable holds a reference, not a copy, so two names can point at the same table.
local a = {1, 2}
local b = a
b[1] = 99
print(a[1])
--> 99
Passing a table to a function passes that same reference, which means the function can rewrite your table from the inside. Usually that is exactly what you want; always it is something to remember.
Your exercise
Sum of List reads a count N, then N integers on their own lines, and prints the total.
The starter already reads everything into a table called nums, so you add the accumulation and one print.
The mistake the grader will catch is the 0-based habit: for i = 0, n - 1 do total = total + nums[i] end reads nums[0], gets nil, and the run dies with attempt to perform arithmetic on a nil value. Write for i = 1, n or, better, for _, v in ipairs(nums). Watch one more: declaring local total = 0 inside the loop resets it every pass so you print only the last number — and the hidden test feeds a single value, so that version still passes it and hides the bug from you.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…