Language lab · Beginner → Scripting
🌙 Lua
Concept → trace → write code → run tests → explain why → improve → mini-project. Start in the browser if you like; set up your own computer when you are ready.
📖 Topics with real code (13)
Every verified output below was produced by running the code with Lua 5.4.9 Copyright (C) 1994-2026 Lua.org, PUC-Rio on 6 Nov 2026. Open a topic to edit the code and run it right here in your browser.
🌱 Beginner (5)
Variables and types
Lua has nil, boolean, number (integer and float), string, table and function. local keeps a variable inside its block. type() shows the type; tonumber and tostring convert.
local age = 15
local height = 1.62
local student = true
local name = "Asha"
print(name, age, height, student)
print(type(age), type(height), type(student), type(name), type(nil), math.type(age), math.type(height))
print(tonumber("88") + 2, 7 // 2, 7 / 2, tostring(90) .. "!")
✅ Verified output
Asha 15 1.62 true number number boolean string nil integer float 90 3 3.5 90!
Operators and boolean logic
.. joins strings, // is floor division, ~= means "not equal". and/or return one of their operands, which gives a handy default idiom.
local a, b = 17, 5 print(a + b, a - b, a * b, a / b, a // b, a % b, a ^ 2) print(a == b, a ~= b, not true) local nickname = nil print(nickname or "no nickname", false and "x" or "default")
✅ Verified output
22 12 85 3.4 3 2 289.0 false true false no nickname default
Conditionals
if … then … elseif … else … end. Only nil and false are false: 0 and "" are true in Lua.
local marks = 78
local grade
if marks >= 90 then grade = "A+"
elseif marks >= 75 then grade = "A"
elseif marks >= 35 then grade = "Pass"
else grade = "Fail" end
print("Grade: " .. grade)
if 0 then print("0 is true in Lua") end
✅ Verified output
Grade: A 0 is true in Lua
Loops
Numeric for (start, stop, step), generic for with ipairs/pairs, while and repeat…until. goto continue is a common way to skip a turn.
for i = 1, 5 do
if i == 3 then goto continue end
print("for " .. i)
::continue::
end
local n = 10
while n > 0 do
if n < 4 then break end
print("while " .. n)
n = n - 3
end
local k = 0
repeat k = k + 1 until k >= 3
print("repeat ran " .. k .. " times")
✅ Verified output
for 1 for 2 for 4 for 5 while 10 while 7 while 4 repeat ran 3 times
Functions
Functions are values. They can take a variable number of arguments (...) and return several results.
local function area(length, width)
width = width or 1
return length * width
end
local function stats(...)
local t, sum = { ... }, 0
for _, v in ipairs(t) do sum = sum + v end
return math.min(...), math.max(...), sum / #t
end
print(area(5, 3), area(7))
print(stats(4, 9, 2, 7))
✅ Verified output
15 7 2 9 5.5
🌿 Intermediate (5)
Tables as arrays
Tables are Lua's only data structure. As arrays they are 1-based; # gives the length; table.insert, table.sort and table.concat help.
local marks = { 72, 95, 64, 88 }
table.insert(marks, 91)
table.sort(marks)
print(table.concat(marks, ", "), "first " .. marks[1], "last " .. marks[#marks])
local squares = {}
for x = 1, 5 do if x % 2 == 1 then squares[#squares + 1] = x * x end end
print(table.concat(squares, " "))
✅ Verified output
64, 72, 88, 91, 95 first 64 last 95 1 9 25
Tables as dictionaries
Tables also map keys to values. pairs walks all keys (in no fixed order, so sort keys to print).
local stock = { pen = 40, book = 12 }
stock.eraser = 25
stock.pen = stock.pen - 5
local keys = {}
for k in pairs(stock) do keys[#keys + 1] = k end
table.sort(keys)
for _, k in ipairs(keys) do print(k, stock[k]) end
local freq = {}
for w in ("the cat and the hat and the bat"):gmatch("%a+") do freq[w] = (freq[w] or 0) + 1 end
print("the=" .. freq.the, "and=" .. freq["and"])
✅ Verified output
book 12 eraser 25 pen 35 the=3 and=2
Strings and patterns
string functions can be called with : on any string. Lua patterns (%d digits, %a letters) power find, match and gsub.
local t = (" GayaGnan learning "):match("^%s*(.-)%s*$")
print(t:upper(), t:gsub("learning", "labs"), #t)
print(string.format("Total: %.2f for %d items", 49.5 * 3, 3))
print(("level"):reverse() == "level")
for num in ("a1b22c333"):gmatch("%d+") do io.write(num, " ") end
print()
✅ Verified output
GAYAGNAN LEARNING GayaGnan labs 17 Total: 148.50 for 3 items true 1 22 333
Objects with metatables
Lua has no classes, but metatables and __index give objects and inheritance. The : syntax passes self.
local Account = {}
Account.__index = Account
function Account.new(owner, balance) return setmetatable({ owner = owner, balance = balance or 0 }, Account) end
function Account:deposit(amount)
assert(amount > 0, "amount must be positive")
self.balance = self.balance + amount
return self
end
local acc = Account.new("Asha", 500):deposit(250)
print(acc.owner, acc.balance)
local Savings = setmetatable({}, { __index = Account })
Savings.__index = Savings
function Savings:addInterest() return self:deposit(self.balance * 0.05) end
local s = setmetatable(Account.new("Ravi", 1000), Savings)
print(s:addInterest().balance)
✅ Verified output
Asha 750 1050.0
Errors with pcall
error() raises an error; pcall runs a function in protected mode and returns false plus the message instead of crashing.
local function withdraw(balance, amount)
if amount > balance then error("need " .. (amount - balance) .. " more", 0) end
return balance - amount
end
print(pcall(withdraw, 100, 30))
print(pcall(withdraw, 100, 150))
local ok, err = pcall(function() return nil + 1 end)
print(ok, (err:gsub("^.-:%d+: ", "")))
✅ Verified output
true 70 false need 50 more false attempt to perform arithmetic on a nil value
🌳 Advanced (3)
Closures
An inner function keeps access to the outer function's local variables. Each counter below has its own count.
local function makeCounter(step) local count = 0 return function() count = count + (step or 1); return count end end local byOne, byTen = makeCounter(), makeCounter(10) byOne(); byOne() print(byOne(), byTen(), byTen()) local function compose(f, g) return function(x) return f(g(x)) end end print(compose(function(x) return x + 1 end, function(x) return x * 2 end)(5))
✅ Verified output
3 10 20 11
Recursion and memoization
A cache table makes recursive Fibonacci fast. Lua 5.4 integers are 64-bit.
local memo = {}
local function fib(n)
if n < 2 then return n end
if not memo[n] then memo[n] = fib(n - 1) + fib(n - 2) end
return memo[n]
end
local out = {}
for i = 0, 9 do out[#out + 1] = fib(i) end
print(table.concat(out, " "), fib(80))
✅ Verified output
0 1 1 2 3 5 8 13 21 34 23416728348467685
Coroutines
Coroutines pause with yield and resume later: cooperative multitasking used by game engines and network servers.
local producer = coroutine.wrap(function()
for i = 1, 3 do coroutine.yield("item " .. i) end
return "done"
end)
print(producer()); print(producer()); print(producer()); print(producer())
local co = coroutine.create(function(a, b) local c = coroutine.yield(a + b); return c * 2 end)
print(coroutine.resume(co, 2, 3))
print(coroutine.resume(co, 10))
print(coroutine.status(co))
✅ Verified output
item 1 item 2 item 3 done true 5 true 20 dead
🛠️ Set up and verify
- Install
winget install DEVCOM.Lua
brew install lua
sudo apt install lua5.4
- Editor: Visual Studio Code with Lua (sumneko).
- Create
hello.luaprint('Hello, GayaGnan!') - Run it and check the version
hello.lua lua -v
- Health check: paste what your terminal printed.
Install one language at a time. These commands only install or print versions; nothing here deletes files. Versions change: check the official page and note the version you installed.
🧭 The 14-lab path
- 00 · Setup and verify — install the runtime and editor, run hello world, print the version, fix PATH
- 01 · Syntax and trace — follow each line and the value of every variable
- 02 · Logic — conditionals and decision trees
- 03 · Loops — trace tables and loop challenges
- 04 · Functions — break problems down and test each piece
- 05 · Data structures — lists, maps, stacks, queues and trees you can see
- 06 · Debugging — bug cases with a hint ladder
- 07 · Algorithms — search, sort and Big-O comparison
- 08 · Files and data — read and write fixture files
- 09 · API or database — talk to a mock API or a sandbox database
- 10 · Testing — write tests and read failing assertions
- 11 · Security — secure coding and dependency hygiene for this language
- 12 · Project — one portfolio mini-project
- 13 · Assessment — quiz, coding test, rubric and an explain-your-answer prompt
📚 Modules
- types
- operators
- conditionals
- loops
- functions
- tables as arrays
- tables as dictionaries
- strings and patterns
- metatables
- pcall
- closures
- memoization
- coroutines
🏗️ Mini-projects
- Text adventure game
- Config-file parser
- Game-engine scripting (concepts)
Projects use synthetic data only.