FANDOM


setmetatable( tbl, metatbl )
Updates the metatable for a table.
tbl
The table whose metatable to modify.

metatbl
The new metatable.

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

As of v0.2.0, PICO-8 now 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 Edit

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

__mod

__pow

__and

__or

__xor

__shl

__shr

__lshr

__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.
__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 Edit

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.

geckojsc posted a metatable tutorial demonstrating adding and subtracting vector values.

-- default attribute values for a "pixel" class
pixel = {
  x = 0,
  y = 0,
  c = 7
}
 
-- the pixel class constructor
function pixel:new(o)
  self.__index = self
  return setmetatable(o or {}, self)
end
 
-- using the pixel class
p1 = pixel:new()
print(p1.x)   -- 0
print(p1.y)   -- 0
 
-- 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

See also Edit

Community content is available under CC-BY-SA unless otherwise noted.