Skip to content
AgileLogics
6 min read

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 returns t.
  • __add, __mul, __eq, ... define operators; __tostring controls tostring and print; __len controls #.

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.