Setmetatable

From Pico-8 Wiki
Jump to navigation Jump to search
setmetatable( tbl, metatbl )
Updates the metatable for a table.
tbl
The table whose metatable to modify.

metatbl
The new metatable.

return-value
The same tbl that was passed in.

In Lua, tables are general purpose objects that contain values and can be manipulated with operators. The default behaviors of operators on a table value are stored in its metatable, using keys such as __index that refer to functions that perform the operator's task.

The setmetatable() function updates the metatable for a table, allowing you to customize the built-in operations. This has several useful applications for creating custom value types in Lua. For example, you can:

  • Define a vector data type that supports arithmetic operators for addition and subtraction
  • Set comparison operators on a new value type to use it with a generic sorting routine, such as sorting displayable objects by their display depth
  • Implement inheritance: construct objects (tables) that refer to another table as a prototype (or class) by setting the __index operator to access the prototype's properties

PICO-8 supports overwriting the __tostring metamethod. Tables can now be concatenated with strings, or printed directly.

PICO-8 includes Lua's rawget(), rawset(), rawlen(), and rawequal() functions, which ignore custom __index, __newindex, __len, and __eq metamethods, respectively.

Note: The return value is just the input, tbl, given back to you, which can be convenient in pseudo-constructors. See pixel:new() in the example below for a demonstration.

Metamethods

A summary of the lua metamethods, as they pertain to pico-8.

__index function(table, key)

Can also be a table.

Used when reading a non-existing key from the table.

Can be bypassed via rawget()

__newindex function(table, key, value)

Can also be a table.

Used when writing a non-existing key to the table.

Can be bypassed via rawset()

__len function(table) Called when getting the length of the table (via #).

Can be bypassed via rawlen()

__eq function(table1, table2) Called when comparing two distinct tables via == or !=,

but only if both have the same __eq metamethod.

Can be bypassed via rawequal()

__lt function(value1, value2) Called when comparing the table via < or >.

Also called when comparing via <= or >=, if __le isn't defined.

__le function(value1, value2) Called when comparing the table via <= or >=.
__add

__sub
__mul
__div
__idiv
__mod
__pow
__and
__or
__xor
__shl
__shr
__lshr
__rotl
__rotr
__concat

function(value1, value2) Called when performing operations on the table.

(Respectively: +, -, *, /, \, %, ^, &, |, ^^, <<, >>, >>>, <<>, >><, ..)

__unm

__not
__peek
__peek2
__peek4

function(table) Called when performing unary operations on the table.

(Respectively: -, ~, @, %, $)

__call function(table, ...) Called when calling the table as if it were a function.
__tostring function(table) Called when calling tostr(), print() and printh() on the table.
__pairs function(table) Called when calling pairs() on the table.

Can be bypassed by using next() directly.

__ipairs function(table) Called when calling ipairs() on the table.

Can be bypassed by using inext() directly.

__metatable any value Returned instead of the real metatable when calling getmetatable().

Also, its presence causes setmetatable() to fail with an error.

__gc - Appears to not be implemented in PICO-8.
__mode "k"/"v"/"kv" Specifies the table has weak keys/values.

(See lua reference manual for more details)

Examples

-- default attribute values for a "pixel" class
pixel = {
  x = 0,
  y = 0,
  c = 7
}
pixel.__index=pixel

-- the pixel class constructor
function pixel:new(o)
  return setmetatable(o or {}, self)
end

-- using the pixel class
p1 = pixel:new()
print(p1.x)   -- 0
print(p1.y)   -- 0
print(p1.c)   -- 7

-- use an instance of pixel to subclass it
-- (prototypical inheritance)
newpixel = pixel:new({y=100})

p2 = newpixel:new()
print(p2.x)   -- 0
print(p2.y)   -- 100

External samples & references

The Lua documentation on metatables includes an example of implementing a set container type, using metamethods to implement set unions and intersections with the + and * operators.

The Lua documentation on objects demonstrates how to use the __index metamethod to implement inheritance.

On the PICO-8 forums, user geckojsc posted a metatable tutorial demonstrating adding and subtracting vector values.

See also