Difference between revisions of "Metatable"

From ComputerCraft Wiki
Jump to: navigation, search
(Metamethods: Spelling corrections and added to tutorials category)
(Improved)
 
(4 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
{{NeedsWork|Not enough info, perhaps incorrect info}}
 
{{NeedsWork|Not enough info, perhaps incorrect info}}
  
A metatable is an addition on to normal tables for adding metamethods, making classes as well as protecting functions.  
+
'''Metatables''' allow us to change the behavior of a {{type|table}}. For instance, using metatables, we can define how Lua computes the expression <code>a+b</code>, where <var>a</var> and <var>b</var> are tables. Whenever Lua tries to add two tables, it checks whether either of them has a metatable and whether that metatable has an <var>__add</var> field. If Lua finds this field, it calls the corresponding value (the so-called metamethod, which should be a {{type|function}}) to compute the sum.
<!-- Possibly more, I don't know about any other application, unfortunately --~~~~ -->
+
<!-- Taken from the Lua PIL (http://www.lua.org/pil/13.html) --~~~~ -->
 
== Setting and getting a metatable ==
 
== Setting and getting a metatable ==
  
You will use setMetatable and getMetatable to set and get metatables.
+
To set the metatable of a table use <code>setmetatable( table, metatable )</code>, where <var>table</var> is the table which's metatable you want to set and <var>metatable</var> is the new metatable of that table.
  
You use getMetatable(table) to get your metatable from a table. It will return the __metatable metafield
+
To get the metatable of a table use <code>getmetatable( table )</code>, where <var>table</var> is the table which's metatable you want to get.
in the table.
+
 
+
setMetatable(table, metatable) to set your table's metatable. It will error if the __metatable metafield
+
is set.
+
 
+
However, if the table has a metatable with the metafield __metatable, it will error when you use setMetatable and return what it is set to when getMetatable is called.
+
  
 +
Note that the <var>__metatable</var> metafield can change the behavior of both above functions, see below for more info.
 +
 
== Metamethods ==
 
== Metamethods ==
  
A metamethod is a type of function which changes the default way a table acts. The table below demonstrates what each
+
A metamethod is a type of function which changes the default behavior of a table. The table below lists what each
one is called, and how each one is used. <br/>
+
one is called, and how each one is used.<br/>
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 25: Line 21:
 
|-
 
|-
 
| __index
 
| __index
| Used when table[variable] is called.
+
| Can be either a {{type|function}} or a {{type|table}}. Triggered whenever a table is being indexed and there is no field under the indexed <var>key</var>. If set to a table then that table is indexed using the same <var>key</var>. If it's a function then that function is called with the <var>table</var> and the <var>key</var> as parameters and its return value is used as the value under that <var>key</var>.
| The variable.
+
| the <var>table</var> and the <var>key</var>
 
|-
 
|-
 
| __newindex
 
| __newindex
| Used like __index, but it is only called when the variable matches an empty space in the table.
+
| Triggered whenever a new (nil, non-existent) field is being assigned in a table.
| The variable.
+
| the <var>table</var>, the <var>key</var> and the new <var>value</var>
 
|-
 
|-
 
| __call
 
| __call
| A metamethod to turn a table's name into a function, or whatever you want it to do.
+
| Called whenever a table is being called as it was a function.
| Function, Tuple
+
| the <var>table</var> and the arguments that where passed the the table-call expression.
 
|-
 
|-
 
| __metatable
 
| __metatable
| Used for protecting metatables, called when getmetatable() is used on the table, setmetatable() just errors.
+
| If present, <code>getmetatable</code> returns its value instead of the actual metatable, <code>setmetatable</code> raises an error.
| Nothing (as far as Unit158 knows)
+
|  
 
|-
 
|-
 
| __mul
 
| __mul
| Used as an operator overloader for multiplication.
+
| Triggered whenever a multiplication operation with a table occurs. Passes the two operands <var>a</var> and <var>b</var>, without telling which of the operands is the table and which is not.
| The two objects being "multiplied".
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __div
 
| __div
| Used as an operator overloader for division.
+
| Triggered whenever a division operation with a table occurs. Behaves similar to <var>__mul</var> metamethod.
| The two objects being "divided".
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __sub
 
| __sub
| Used as an operator overloader for substraction.
+
| Triggered whenever a subtraction operation with a table occurs. Behaves similar to <var>__mul</var> metamethod.
| The two objects being "subtracted".
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __add
 
| __add
| Used as an operator overloader for addition.
+
| Triggered whenever an addition operation with a table occurs. Behaves similar to <var>__mul</var> metamethod.
| The two objects being "added".
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __mod
 
| __mod
| Used as an operator overloader for modulo.
+
| Triggered whenever a modulo operation with a table occurs. Behaves similar to <var>__mul</var> metamethod.
| The two objects being "divided".
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __pow
 
| __pow
| Used as an operator overloader for exponentiation operation.
+
| Triggered whenever a exponentiation (power) operation with a table occurs. Behaves similar to <var>__mul</var> metamethod.
| The two objects being exponentiated.
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __unm
 
| __unm
| I am not exactly sure how this one works, it is for negatives though.
+
| Triggered whenever the unary ( <code>-table</code> ) operator is used on a table.
| The table being changed into a negative. <!-- Feel free to change this one X] -->
+
| the <var>table</var>
 
|-
 
|-
 
| __eq
 
| __eq
| __eq is an operator overloader for comparison.
+
| Triggered whenever an "equal" ( == ) operation is performed on two tables with the exact same metatable. If the metatable does not match - returns false.
| The two objects being compared
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __lt
 
| __lt
| Less than.
+
| Triggered whenever a "less than" ( < ), or "more than" ( > ), operation is performed on the table. Similarly to the <var>__mul</var> metamethod it is not known which parameter is which.
| The two objects being compared
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __le
 
| __le
| Less than or equal to.
+
| Triggered whenever a "less than or equal to" ( <= ), or "less than or equal to" ( >= ), operation is performed on the table. Similarly to the <var>__mul</var> metamethod it is not known which parameter is which.
| The objects being compared
+
| operand <var>a</var> and operand <var>b</var>
 
|-
 
|-
 
| __concat
 
| __concat
| The objects being concatenated
+
| Triggered whenever a concatenation ( .. ) operation is performed on the table. Similarly to the <var>__mul</var> metamethod it is not known which parameter is which.
| The two objects being concatenated
+
| operand <var>a</var> and operand <var>b</var>
|-
+
| __len
+
| The # operator.
+
| The object having the operation performed on it.
+
|-
+
 
|}
 
|}
 +
 +
== Examples ==
 +
{{Example
 +
|desc=Use __eq to check if two tables are equal
 +
|code=table1 = {x=0, y=1, z=0}
 +
table2 = {x=1, y=1, z=0}
 +
metatable = {__eq = function(operand1, operand2, type)
 +
if operand1.x == operand2.x and operand1.y == operand2.y and operand1.z then --Note: In reality you might want to first check if your these variables actually exist
 +
    return true
 +
else
 +
    return false
 +
end }
 +
setmetatable(table1, metatable)
 +
setmetatable(table2, metatable)
 +
if table1 == table2 then
 +
    print("Equal")
 +
else
 +
    print("Not equal")
 +
end
 +
}}
 +
== External links ==
 +
* [http://www.lua.org/manual/5.1/manual.html#2.8 Lua 5.1 Reference Manual: Metatables]
  
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]

Latest revision as of 19:18, 12 May 2015

This page needs some serious TLC, stat!
Please help us by cleaning it, fixing it up, or sparing it some love.
(Reason: Not enough info, perhaps incorrect info)

Metatables allow us to change the behavior of a table. For instance, using metatables, we can define how Lua computes the expression a+b, where a and b are tables. Whenever Lua tries to add two tables, it checks whether either of them has a metatable and whether that metatable has an __add field. If Lua finds this field, it calls the corresponding value (the so-called metamethod, which should be a function) to compute the sum.

Setting and getting a metatable

To set the metatable of a table use setmetatable( table, metatable ), where table is the table which's metatable you want to set and metatable is the new metatable of that table.

To get the metatable of a table use getmetatable( table ), where table is the table which's metatable you want to get.

Note that the __metatable metafield can change the behavior of both above functions, see below for more info.

Metamethods

A metamethod is a type of function which changes the default behavior of a table. The table below lists what each one is called, and how each one is used.

Name Description Arguments passed
__index Can be either a function or a table. Triggered whenever a table is being indexed and there is no field under the indexed key. If set to a table then that table is indexed using the same key. If it's a function then that function is called with the table and the key as parameters and its return value is used as the value under that key. the table and the key
__newindex Triggered whenever a new (nil, non-existent) field is being assigned in a table. the table, the key and the new value
__call Called whenever a table is being called as it was a function. the table and the arguments that where passed the the table-call expression.
__metatable If present, getmetatable returns its value instead of the actual metatable, setmetatable raises an error.
__mul Triggered whenever a multiplication operation with a table occurs. Passes the two operands a and b, without telling which of the operands is the table and which is not. operand a and operand b
__div Triggered whenever a division operation with a table occurs. Behaves similar to __mul metamethod. operand a and operand b
__sub Triggered whenever a subtraction operation with a table occurs. Behaves similar to __mul metamethod. operand a and operand b
__add Triggered whenever an addition operation with a table occurs. Behaves similar to __mul metamethod. operand a and operand b
__mod Triggered whenever a modulo operation with a table occurs. Behaves similar to __mul metamethod. operand a and operand b
__pow Triggered whenever a exponentiation (power) operation with a table occurs. Behaves similar to __mul metamethod. operand a and operand b
__unm Triggered whenever the unary ( -table ) operator is used on a table. the table
__eq Triggered whenever an "equal" ( == ) operation is performed on two tables with the exact same metatable. If the metatable does not match - returns false. operand a and operand b
__lt Triggered whenever a "less than" ( < ), or "more than" ( > ), operation is performed on the table. Similarly to the __mul metamethod it is not known which parameter is which. operand a and operand b
__le Triggered whenever a "less than or equal to" ( <= ), or "less than or equal to" ( >= ), operation is performed on the table. Similarly to the __mul metamethod it is not known which parameter is which. operand a and operand b
__concat Triggered whenever a concatenation ( .. ) operation is performed on the table. Similarly to the __mul metamethod it is not known which parameter is which. operand a and operand b

Examples

Grid paper.png  Example
Use __eq to check if two tables are equal
Code
table1 = {x=0, y=1, z=0}
table2 = {x=1, y=1, z=0}
metatable = {__eq = function(operand1, operand2, type)
if operand1.x == operand2.x and operand1.y == operand2.y and operand1.z then --Note: In reality you might want to first check if your these variables actually exist
    return true
else
    return false
end }
setmetatable(table1, metatable)
setmetatable(table2, metatable)
if table1 == table2 then
    print("Equal")
else
    print("Not equal")
end



External links