Lua Academy · Lesson

Nested Tables and Structured Data

Build nested structures and access deep fields.

Lesson 4 of 412 steps

Nested Tables and Structured Data is a free Lua Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, and your progress syncs across the web and the CoddyKit app. The Lua Academy course includes 4 lessons in total.

Nested Table Basics

Tables can contain other tables as values, creating arbitrarily deep structures. Access nested fields by chaining dots or brackets. Missing intermediate tables cause errors — always ensure parent tables exist before accessing deep fields.

local company = {
  name = "CoddyKit",
  address = {
    city = "Istanbul",
    country = "Turkey",
    zip = "34000"
  },
  employees = 25
}

print(company.name)            -- CoddyKit
print(company.address.city)    -- Istanbul
print(company["address"]["zip"]) -- 34000

Safe Deep Access

Accessing a field on a nil value crashes with "attempt to index a nil value". Guard against this with the and short-circuit: t and t.a and t.a.b. Some codebases define a get(t, ...) helper that safely traverses a chain of keys.

local function get(t, ...)
  local cur = t
  for _, key in ipairs({...}) do
    if type(cur) ~= "table" then return nil end
    cur = cur[key]
  end
  return cur
end

local data = {user = {profile = {age = 30}}}
print(get(data, "user", "profile", "age"))    -- 30
print(get(data, "user", "missing", "field"))  -- nil

Array of Records

A common pattern is an array of tables (records). Each element is a table with named fields. Iterate with ipairs and access fields by name. This is Lua's equivalent of an array of objects or a list of structs.

local users = {
  {id=1, name="Alice", score=95},
  {id=2, name="Bob",   score=87},
  {id=3, name="Carol", score=91},
}

for _, user in ipairs(users) do
  print(user.id, user.name, user.score)
end

Building Nested Tables Dynamically

Build nested structures incrementally by creating inner tables as needed. Always initialize a table before inserting into it. A common mistake is forgetting to create the inner table first, then trying to index nil.

local tree = {}
tree.root = {value = 10}
tree.root.left = {value = 5}
tree.root.right = {value = 15}
tree.root.left.left = {value = 2}

print(tree.root.value)            -- 10
print(tree.root.left.value)       -- 5
print(tree.root.left.left.value)  -- 2

Table as JSON-Like Config

Lua tables are often used for configuration files, similar to JSON or YAML. The file returns a table, and the application loads it with dofile() or require(). Nested tables represent nested config sections.

-- config.lua (returned table)
local config = {
  server = {
    host = "0.0.0.0",
    port = 8080,
    ssl  = false,
  },
  db = {
    host = "localhost",
    name = "appdb",
    pool_size = 10,
  },
  logging = { level = "info", file = "/var/log/app.log" }
}

print(config.server.port)      -- 8080
print(config.db.pool_size)    -- 10

Graph as Adjacency List

Represent a graph as a table of tables: each key is a node, and its value is a list of neighbors. This adjacency list representation is memory-efficient for sparse graphs and easy to work with in Lua.

local graph = {
  A = {"B", "C"},
  B = {"A", "D"},
  C = {"A", "D"},
  D = {"B", "C"},
}

-- BFS from A
local visited = {A=true}
local queue = {"A"}
while #queue > 0 do
  local node = table.remove(queue, 1)
  io.write(node .. " ")
  for _, neighbor in ipairs(graph[node]) do
    if not visited[neighbor] then
      visited[neighbor] = true
      queue[#queue+1] = neighbor
    end
  end
end
print()  -- A B C D

Modifying Nested Fields

Modify nested fields by accessing the parent table and assigning to the key. Since tables are passed by reference, any function that receives a table can modify its contents in-place — the caller sees the changes.

local player = {name="Hero", stats={hp=100, mp=50, atk=20}}

local function takeDamage(p, dmg)
  p.stats.hp = math.max(0, p.stats.hp - dmg)
end

takeDamage(player, 35)
print(player.stats.hp)   -- 65

player.stats.atk = player.stats.atk + 5
print(player.stats.atk)  -- 25

Serializing Nested Tables

Converting a nested table to a string is useful for debugging or logging. A simple recursive serializer handles any depth, though it won't handle cycles (circular references).

local function serialize(val, indent)
  indent = indent or 0
  local pad = string.rep("  ", indent)
  if type(val) ~= "table" then
    return tostring(val)
  end
  local parts = {"{"}
  for k, v in pairs(val) do
    parts[#parts+1] = pad.."  "..tostring(k).."="..serialize(v,indent+1)
  end
  parts[#parts+1] = pad.."}"
  return table.concat(parts, "\n")
end
local data = {x=1, nested={y=2, z=3}}
print(serialize(data))

Sparse Matrices

A 2D matrix stored naively wastes memory for large sparse inputs. Store only non-zero entries in a nested table: matrix[row][col] = value. This can represent huge matrices efficiently when most values are zero.

local function newMatrix()
  return setmetatable({}, {__index=function(t,k)
    local row = {}
    rawset(t, k, row)
    return row
  end})
end

local m = newMatrix()
m[1][1] = 5
m[3][7] = 12
m[100][200] = 99

print(m[1][1])    -- 5
print(m[3][7])    -- 12
print(m[2][5])    -- nil (sparse: no value)

Deep Equality Check

Tables compare by reference with ==, not by value. To compare nested tables structurally, write a recursive equality function that compares each key-value pair and recurses into nested tables.

local function deepEqual(a, b)
  if type(a) ~= type(b) then return false end
  if type(a) ~= "table" then return a == b end
  for k, v in pairs(a) do
    if not deepEqual(v, b[k]) then return false end
  end
  for k in pairs(b) do
    if a[k] == nil then return false end
  end
  return true
end
print(deepEqual({1,{2,3}},{1,{2,3}}))  -- true
print(deepEqual({1,{2,3}},{1,{2,4}}))  -- false

Quick Check

What happens when you access t.a.b and t.a is nil?

Recap: Nested Tables

Summary:

  • Tables nest arbitrarily: t.a.b.c
  • Guard deep access: t and t.a and t.a.b
  • Tables are reference types — functions modify in-place
  • Array of records: {{name=...},{name=...}}
  • Sparse matrix: nested tables for memory efficiency
  • Deep equality requires recursive comparison
Free to start

Learn Lua with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
40
Lessons
159

Frequently Asked Questions

Is the “Nested Tables and Structured Data” lesson free?

Yes — any 3 lessons of the Lua Academy learning path, including “Nested Tables and Structured Data”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Lua Academy course includes 4 lessons in total.

What will I learn in “Nested Tables and Structured Data”?

Build nested structures and access deep fields. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Lua Academy?

No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “Nested Tables and Structured Data” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Lua Academy lesson?

Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Tables as Arrays
  2. Tables as Dictionaries
  3. Iterating Tables with pairs and ipairs
  4. Nested Tables and Structured Data
← Back to Lua Academy