Metatables and Metamethods
Prerequisites: Advanced tables
A metatable changes how a table behaves. It holds special fields —
metamethods — that Lua calls for operations like +, ==,
tostring, or reading a missing key.
local Vector = {}
Vector.__index = Vector
local function vec(x, y)
return setmetatable({x = x, y = y}, Vector)
end
Vector.__add = function(a, b) return vec(a.x + b.x, a.y + b.y) end
Vector.__mul = function(a, k) return vec(a.x * k, a.y * k) end
Vector.__eq = function(a, b) return a.x == b.x and a.y == b.y end
Vector.__tostring = function(v) return "(" .. v.x .. ", " .. v.y .. ")" end
Vector.__len = function(v) return math.sqrt(v.x ^ 2 + v.y ^ 2) end
local a, b = vec(1, 2), vec(3, 4)
print(tostring(a + b))
print(tostring(a * 3))
print(a == vec(1, 2))
print(#b)
print(getmetatable(a) == Vector)
(4, 6)
(3, 6)
true
5.0
true
setmetatable(t, mt)attaches a metatable and returnst.__add,__mul,__eq, ... define operators;__tostringcontrolstostringandprint;__lencontrols#.
Common metamethods
| Metamethod | Triggered by |
|---|---|
__add, __sub, __mul, __div, __mod, __pow, __unm, __idiv |
arithmetic |
__eq, __lt, __le |
==, <, <= (and >, >= by swapping) |
__concat |
.. |
__len |
# |
__call |
calling the table like a function |
__tostring |
tostring() |
__index |
reading a missing key |
__newindex |
writing a new key |
__close |
leaving the scope of a <close> variable (5.4) |
__gc |
garbage collection |
__call and __lt
local Money = {}
Money.__index = Money
Money.__lt = function(a, b) return a.cents < b.cents end
Money.__tostring = function(m) return string.format("$%.2f", m.cents / 100) end
setmetatable(Money, {
__call = function(_, cents) return setmetatable({cents = cents}, Money) end,
})
local prices = {Money(1999), Money(500), Money(12000)}
table.sort(prices, function(a, b) return a < b end)
for _, p in ipairs(prices) do print(tostring(p)) end
print(Money(1) < Money(2))
$5.00
$19.99
$120.00
true
Giving the Money table itself a metatable with __call lets you write
Money(1999) as a constructor.
Metatables are Lua's main extension mechanism — the next lessons use them for defaults, read-only tables, and classes.