🎓 A1Learner
🔍
0 of 47 lessons completed

Lua Metatables

A metatable is a table that holds extra behaviour for another table. Attaching one can teach an operator like + how to work with that table.

Adding two vectors the manual way

Without a metatable, each field must be added by hand into a new table. The printed fields show the sums this manual work produces.

local a = {x = 3, y = 4}
local b = {x = 1, y = 2}
local c = {x = a.x + b.x, y = a.y + b.y}
print(c.x, c.y)

__add teaches + to add vectors

Both vectors share one metatable whose __add field builds the summed vector. The same sums now come from a single + sign.

local mt = {
  __add = function(a, b)
    return {x = a.x + b.x, y = a.y + b.y}
  end
}
local a = setmetatable({x = 3, y = 4}, mt)
local b = setmetatable({x = 1, y = 2}, mt)
local c = a + b
print(c.x, c.y)

__tostring gives print a string to show

Printing a table value is allowed here only because __tostring replaces the usual table address with a string. print shows exactly the string that field returns.

local mt = {
  __tostring = function(p)
    return "(" .. p.x .. ", " .. p.y .. ")"
  end
}
local point = setmetatable({x = 3, y = 4}, mt)
print(point)

Example

local mt = {}
mt.__add = function(a, b)
  return setmetatable({amount = a.amount + b.amount}, mt)
end
mt.__tostring = function(m)
  return string.format("%.2f USD", m.amount)
end
local a = setmetatable({amount = 12.5}, mt)
local b = setmetatable({amount = 7.25}, mt)
local total = a + b
print(total)

Key points

  • Metatable: a table that holds extra behaviour for another table.
  • setmetatable(): attaches a metatable to a table and returns that table.
  • __add: a field in the metatable that tells Lua what + should do with the table.
  • __tostring: a field in the metatable that tells print what string to show for the table.
  • Plain fields: a table with a metatable still stores and reads its own fields in the normal way.

In this example, a money table carries one field named amount. Its metatable adds two amounts with __add and gives the total the same metatable. Its __tostring field formats the amount with string.format("%.2f USD"), so printing the total shows 19.75 USD.

Note

most tables in this course have no metatable, so + and print keep their plain meanings for them.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does setmetatable(t, mt) do?