A language tour
260KB. One data structure. Embeds in anything. The smallest language with the largest footprint you've never noticed.
01 โ The Embedded Language
Lua is embedded in World of Warcraft, Roblox, Redis, Nginx, Wireshark, VLC, and thousands of games. Its entire runtime is 260 kilobytes. It was designed from the start to be hosted inside another application โ the perfect scripting companion.
"Lua means 'moon' in Portuguese. It is not an acronym. And it has always been written 'Lua', not 'LUA'."
โ Lua FAQ, Roberto Ierusalimschy-- Lua syntax is clean and minimal print("Hello, world!") -- Variables are global by default โ use local local name = "Lua" local year = 1993 print(string.format("%s was born in %d", name, year)) -- The runtime is tiny โ 260KB for the entire interpreter -- No dependencies, no standard library bloat -- Just: tables, coroutines, closures, metatables, and C API
Lua's small footprint is not an accident โ it's the primary design goal. Every language feature was considered through the lens of: "does this pay its weight in the embedded use case?"
02 โ Tables
Lua has exactly one composite data structure: the table. It's an array. It's a hash map. It's a set. It's an object. It's a namespace. It's a module. The entire language is built on this one idea, and it's remarkably powerful.
-- A table as array (1-indexed!) local fruits = {"apple", "banana", "cherry"} print(fruits[1]) -- "apple" โ Lua arrays start at 1 -- A table as hash map local config = { host = "localhost", port = 8080, debug = true } -- A table as object local point = { x = 3, y = 4 } function point:length() return math.sqrt(self.x^2 + self.y^2) end print(point:length()) -- 5.0
The colon syntax in point:length() is syntactic sugar โ it's equivalent to point.length(point), passing the table as the first argument. Objects in Lua are just tables with a calling convention.
03 โ Metatables
Metatables give tables special behaviour when you try to access missing keys, do arithmetic, or call them as functions. OOP, operator overloading, proxies โ all built from this one mechanism.
local Vector = {} Vector.__index = Vector function Vector.new(x, y) return setmetatable({ x=x, y=y }, Vector) end -- __add is called when + is used on two vectors function Vector:__add(other) return Vector.new(self.x + other.x, self.y + other.y) end -- __tostring controls print() output function Vector:__tostring() return string.format("(%g, %g)", self.x, self.y) end local a = Vector.new(1, 2) local b = Vector.new(3, 4) print(tostring(a + b)) -- (4, 6)
__index, __add, __tostring โ metamethods are the hooks that let tables intercept and respond to language operations. Everything in Lua that looks like OOP is built from these hooks.
04 โ Coroutines
Lua has native coroutines โ functions that can pause themselves and hand control back to the caller. No threads, no locks, no race conditions. Coroutines enabled async patterns in Lua long before they were fashionable in other languages.
-- A generator using coroutines local function range(from, to) return coroutine.wrap(function() for i = from, to do coroutine.yield(i) end end) end for n in range(1, 5) do io.write(n .. " ") end -- 1 2 3 4 5 -- Producer-consumer without threads local producer = coroutine.create(function() for i = 1, 3 do coroutine.yield("item_" .. i) end end)
coroutine.wrap returns a plain function โ calling it resumes the coroutine and returns the yielded value. This pattern is Lua's equivalent of Python generators, introduced over a decade earlier.
05 โ Closures
Lua has first-class functions and closures โ functions capture the variables of their enclosing scope. This is the foundation of Lua's module system, the OOP pattern, and most of its higher-order programming idioms.
-- A counter factory โ each call gets its own count local function make_counter(start) local count = start return { inc = function() count = count + 1 end, get = function() return count end, reset = function() count = start end } end local c = make_counter(10) c.inc(); c.inc() print(c.get()) -- 12 c.reset() print(c.get()) -- 10
Each call to make_counter creates a new upvalue โ a shared variable captured by all three returned functions. This is encapsulation in Lua: private state through closures, not classes.
06 โ The Whole Picture
World of Warcraft, Roblox, CryEngine, Defold โ if a game has a scripting layer, it's probably Lua.
LuaJIT is one of the fastest dynamic language runtimes ever built. Competitive with compiled languages on numeric code.
The entire interpreter is a handful of C files. No external libraries, no build system โ just drop it in and compile.
The C API is excellent โ bidirectional, stack-based, and stable. Extending Lua from C is genuinely pleasant.
Nginx + LuaJIT runs some of the highest-traffic sites on the web. Lua scripting at the HTTP layer.
"Programming in Lua" by the language's creator is still one of the best programming language books ever written.