Drill 02: Tables

Tables: THE data structure in Lua. Arrays, dictionaries, nested structures.

Run This Drill

bash ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/examples/lua-drills/02-tables.sh

Drill Script

#!/bin/bash
# LUA DRILL 02: TABLES
# Paste this entire script into your terminal
# Topics: Arrays, dictionaries, nested tables, iteration

echo "=================================================================="
echo "             LUA DRILL 02: TABLES                                "
echo "=================================================================="
echo ""
echo "Tables are THE data structure in Lua - arrays, dicts, objects."
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 2.1: ARRAY-STYLE TABLES"
echo "Indexed by number, starting at 1 (not 0!)"
echo "------------------------------------------------------------------"
echo ""
lua << 'LUAEOF'
-- Create array
local hosts = {"ise-01", "ise-02", "bind-01"}

print("Array:", hosts[1], hosts[2], hosts[3])
print("Length:", #hosts)  -- 3

-- Add to end
table.insert(hosts, "vault-01")
print("\nAfter insert:", #hosts, "items")

-- Remove from end
local removed = table.remove(hosts)
print("Removed:", removed)

-- Insert at position
table.insert(hosts, 1, "gateway")
print("After insert at 1:", hosts[1])

-- IMPORTANT: Lua arrays start at 1!
for i = 1, #hosts do
    print("  hosts[" .. i .. "] =", hosts[i])
end
LUAEOF
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 2.2: DICTIONARY-STYLE TABLES"
echo "Key-value pairs"
echo "------------------------------------------------------------------"
echo ""
lua << 'LUAEOF'
-- Create dictionary
local server = {
    hostname = "ise-01",
    ip = "10.50.1.20",
    port = 443,
    enabled = true
}

-- Access with dot notation
print("Dot notation:", server.hostname)

-- Access with bracket notation
print("Bracket notation:", server["ip"])

-- Dynamic keys need brackets
local key = "port"
print("Dynamic key:", server[key])

-- Add new key
server.status = "active"
print("New key:", server.status)

-- Keys with special chars need brackets
server["full-name"] = "ise-01.example.com"
print("Special key:", server["full-name"])

-- Check if key exists
if server.missing == nil then
    print("\n'missing' key does not exist")
end
LUAEOF
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 2.3: MIXED TABLES"
echo "Arrays with dictionary parts"
echo "------------------------------------------------------------------"
echo ""
lua << 'LUAEOF'
-- Common pattern: list with metadata
local result = {
    -- Array part
    "item1",
    "item2",
    "item3",
    -- Dictionary part
    count = 3,
    status = "success"
}

print("Array part:")
for i = 1, #result do
    print("  [" .. i .. "] =", result[i])
end

print("\nDictionary part:")
print("  count =", result.count)
print("  status =", result.status)
LUAEOF
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 2.4: ITERATION"
echo "ipairs for arrays, pairs for dicts"
echo "------------------------------------------------------------------"
echo ""
lua << 'LUAEOF'
local hosts = {"ise-01", "ise-02", "bind-01"}

-- ipairs: numeric keys in order (for arrays)
print("ipairs (array iteration):")
for i, host in ipairs(hosts) do
    print("  [" .. i .. "]", host)
end

local server = {
    hostname = "ise-01",
    ip = "10.50.1.20",
    port = 443
}

-- pairs: all keys (order not guaranteed)
print("\npairs (dictionary iteration):")
for key, value in pairs(server) do
    print("  " .. key .. " =", value)
end

-- Common pattern: filter during iteration
print("\nFiltering:")
local numbers = {10, 25, 5, 30, 15}
for i, n in ipairs(numbers) do
    if n > 20 then
        print("  Found > 20:", n)
    end
end
LUAEOF
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 2.5: NESTED TABLES"
echo "Tables within tables"
echo "------------------------------------------------------------------"
echo ""
lua << 'LUAEOF'
-- Nested structure (like JSON)
local inventory = {
    servers = {
        {hostname = "ise-01", ip = "10.50.1.20", roles = {"pan", "mnt"}},
        {hostname = "ise-02", ip = "10.50.1.21", roles = {"psn"}},
    },
    vlans = {
        management = 50,
        data = 10
    }
}

-- Access nested
print("First server:", inventory.servers[1].hostname)
print("First server IP:", inventory.servers[1].ip)
print("First server first role:", inventory.servers[1].roles[1])
print("Management VLAN:", inventory.vlans.management)

-- Iterate nested
print("\nAll servers:")
for i, server in ipairs(inventory.servers) do
    print(string.format("  %s (%s)", server.hostname, server.ip))
    print("    Roles:", table.concat(server.roles, ", "))
end
LUAEOF
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 2.6: TABLE UTILITIES"
echo "Useful table functions"
echo "------------------------------------------------------------------"
echo ""
lua << 'LUAEOF'
-- table.concat - join array elements
local hosts = {"ise-01", "ise-02", "bind-01"}
print("concat:", table.concat(hosts, ", "))
print("concat with newline:\n" .. table.concat(hosts, "\n"))

-- table.sort - in-place sort
local numbers = {30, 10, 50, 20, 40}
table.sort(numbers)
print("\nsorted:", table.concat(numbers, ", "))

-- Sort with custom function
local servers = {
    {name = "zzz", cpu = 10},
    {name = "aaa", cpu = 50},
    {name = "mmm", cpu = 30}
}
table.sort(servers, function(a, b) return a.cpu < b.cpu end)
print("\nSorted by CPU:")
for _, s in ipairs(servers) do
    print(string.format("  %s: %d%%", s.name, s.cpu))
end

-- Copy table (shallow)
local function shallow_copy(t)
    local copy = {}
    for k, v in pairs(t) do
        copy[k] = v
    end
    return copy
end

local original = {a = 1, b = 2}
local copied = shallow_copy(original)
copied.c = 3
print("\noriginal:", original.c)  -- nil
print("copy:", copied.c)          -- 3
LUAEOF
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "YOUR TURN - TRY THESE IN nvim :lua"
echo "------------------------------------------------------------------"
echo ""
echo "1. Create and iterate array:"
echo "   :lua for i, v in ipairs({'a', 'b', 'c'}) do print(i, v) end"
echo ""
echo "2. Create dict and access:"
echo "   :lua local t = {x=1, y=2}; print(t.x)"
echo ""
echo "3. Table concat:"
echo "   :lua print(table.concat({'a', 'b', 'c'}, '-'))"
echo ""
echo "------------------------------------------------------------------"
echo "KEY TAKEAWAYS:"
echo "1. Tables are 1-indexed (NOT 0!)"
echo "2. #table gives length of array part"
echo "3. ipairs for arrays, pairs for dicts"
echo "4. table.insert/remove for array ops"
echo "5. table.concat for joining strings"
echo "6. table.sort for sorting (in-place)"
echo "------------------------------------------------------------------"