A metatable changes how a Lua value reacts to predefined operations. When ordinary table addition is undefined, for example, Lua looks for an __add metamethod and calls it.
A vector type
1 | local Vector = {} |
Arithmetic metamethods include __add, __sub, __mul, __div, __mod, __pow, and unary __unm, with additions depending on the Lua version. Comparison uses __eq, __lt, and __le. Do not mutate operands inside an arithmetic metamethod unless that behavior is explicitly part of the type’s contract.
__index and __newindex
When a key is absent, __index may be a table to continue lookup or a function to compute the result:
1 | local defaults = { color = "blue", size = 12 } |
__newindex intercepts assignment to an absent key. Use rawget and rawset inside these handlers when access must bypass metamethods and avoid recursion.
1 | local readOnly = setmetatable({}, { |
This proxy prevents normal assignment through readOnly, but it does not make the original settings table immutable if other code still holds it.
Other useful metamethods include __call for callable values, __len for length, __pairs in supported versions, __concat, and __gc for finalization of suitable objects. Metamethods are powerful language hooks; keep their behavior unsurprising and document any version-specific semantics.