We call the keys in a metatable events and the values metamethods. In the previous example, the event is "add" and the metamethod is the function that performs the addition.

    You can query the metatable of any value through the function.

    You can replace the metatable of tables through the setmetatable function. You cannot change the metatable of other types from Lua (except by using the debug library); you must use the C API for that.

    Tables and full userdata have individual metatables (although multiple tables and userdata can share their metatables). Values of all other types share one single metatable per type; that is, there is one single metatable for all numbers, one for all strings, etc.

    A metatable controls how an object behaves in arithmetic operations, order comparisons, concatenation, length operation, and indexing. A metatable also can define a function to be called when a userdata is garbage collected. For each of these operations Lua associates a specific key called an event. When Lua performs one of these operations over a value, it checks whether this value has a metatable with the corresponding event. If so, the value associated with that key (the metamethod) controls how Lua will perform the operation.

    Metatables control the operations listed next. Each operation is identified by its corresponding name. The key for each operation is a string with its name prefixed by two underscores, ‘__‘; for instance, the key for operation “add” is the string "__add". The semantics of these operations is better explained by a Lua function describing how the interpreter executes the operation.

    The code shown here in Lua is only illustrative; the real behavior is hard coded in the interpreter and it is much more efficient than this simulation. All functions used in these descriptions (, tonumber, etc.) are described in . In particular, to retrieve the metamethod of a given object, we use the expression

    This should be read as

    1. rawget(getmetatable(obj) or {}, event)
    • “add”: the + operation.

      The function getbinhandler below defines how Lua chooses a handler for a binary operation. First, Lua tries the first operand. If its type does not define a handler for the operation, then Lua tries the second operand.

      1. function getbinhandler (op1, op2, event)
      2. return metatable(op1)[event] or metatable(op2)[event]
      3. end

      By using this function, the behavior of the op1 + op2 is

      1. function add_event (op1, op2)
      2. local o1, o2 = tonumber(op1), tonumber(op2)
      3. if o1 and o2 then -- both operands are numeric?
      4. return o1 + o2 -- '+' here is the primitive 'add'
      5. else -- at least one of the operands is not numeric
      6. local h = getbinhandler(op1, op2, "__add")
      7. if h then
      8. -- call the handler with both operands
      9. return (h(op1, op2))
      10. else -- no handler available: default behavior
      11. error(···)
      12. end
      13. end
      14. end
    • “sub”: the operation. Behavior similar to the “add” operation.

    • “mul”: the * operation. Behavior similar to the “add” operation.
    • “div”: the / operation. Behavior similar to the “add” operation.
    • “mod”: the % operation. Behavior similar to the “add” operation, with the operation o1 - floor(o1/o2)*o2 as the primitive operation.
    • “pow”: the ^ (exponentiation) operation. Behavior similar to the “add” operation, with the function pow (from the C math library) as the primitive operation.
    • “unm”: the unary - operation.

    • “concat”: the .. (concatenation) operation.

      1. function concat_event (op1, op2)
      2. if (type(op1) == "string" or type(op1) == "number") and
      3. (type(op2) == "string" or type(op2) == "number") then
      4. return op1 .. op2 -- primitive string concatenation
      5. else
      6. local h = getbinhandler(op1, op2, "__concat")
      7. if h then
      8. return (h(op1, op2))
      9. else
      10. error(···)
      11. end
      12. end
      13. end
    • “len”: the # operation.

      1. function len_event (op)
      2. if type(op) == "string" then
      3. elseif type(op) == "table" then
      4. return #op -- primitive table length
      5. else
      6. local h = metatable(op).__len
      7. if h then
      8. -- call the handler with the operand
      9. return (h(op))
      10. else -- no handler available: default behavior
      11. error(···)
      12. end
      13. end
      14. end

      See §2.5.5 for a description of the length of a table.

      1. function getcomphandler (op1, op2, event)
      2. if type(op1) ~= type(op2) then return nil end
      3. local mm1 = metatable(op1)[event]
      4. local mm2 = metatable(op2)[event]
      5. if mm1 == mm2 then return mm1 else return nil end
      6. end

      The “eq” event is defined as follows:

      a ~= b is equivalent to not (a == b).

    • “lt”: the < operation.

      1. function lt_event (op1, op2)
      2. if type(op1) == "number" and type(op2) == "number" then
      3. return op1 < op2 -- numeric comparison
      4. elseif type(op1) == "string" and type(op2) == "string" then
      5. return op1 < op2 -- lexicographic comparison
      6. else
      7. local h = getcomphandler(op1, op2, "__lt")
      8. if h then
      9. return (h(op1, op2))
      10. else
      11. error(···)
      12. end
      13. end
      14. end

      a > b is equivalent to b < a.

    • “le”: the <= operation.

      1. function le_event (op1, op2)
      2. if type(op1) == "number" and type(op2) == "number" then
      3. return op1 <= op2 -- numeric comparison
      4. elseif type(op1) == "string" and type(op2) == "string" then
      5. return op1 <= op2 -- lexicographic comparison
      6. else
      7. local h = getcomphandler(op1, op2, "__le")
      8. return (h(op1, op2))
      9. else
      10. h = getcomphandler(op1, op2, "__lt")
      11. if h then
      12. return not h(op2, op1)
      13. else
      14. error(···)
      15. end
      16. end
      17. end
      18. end

      a >= b is equivalent to b <= a. Note that, in the absence of a “le” metamethod, Lua tries the “lt”, assuming that a <= b is equivalent to not (b < a).

    • “index”: The indexing access .

      1. function gettable_event (table, key)
      2. local h
      3. if type(table) == "table" then
      4. local v = rawget(table, key)
      5. if v ~= nil then return v end
      6. h = metatable(table).__index
      7. if h == nil then return nil end
      8. else
      9. h = metatable(table).__index
      10. if h == nil then
      11. error(···)
      12. end
      13. end
      14. if type(h) == "function" then
      15. return (h(table, key)) -- call the handler
      16. else return h[key] -- or repeat operation on it
      17. end
      18. end
    • “newindex”: The indexing assignment table[key] = value.

      1. function function_event (func, ...)
      2. if type(func) == "function" then
      3. return func(...) -- primitive call
      4. else
      5. local h = metatable(func).__call
      6. if h then
      7. return h(func, ...)
      8. else
      9. error(···)
      10. end
      11. end