Lua Metatables

In this article, we’ll explore the concept of Lua metatables, how to use them, and some practical examples.

Tables that define the behavior of other tables are known as metatables.



Lua Metatables – What are they?

Lua metatable is a table that is associated with another table, and which provides additional functionality to that table.

A metatable can be used to customize the behavior of tables in various ways, such as changing how Lua performs arithmetic operations on them, or adding new methods and properties to tables.

Metatables can also be used to create custom data-types in Lua, and to implement object-oriented programming techniques.

In Lua, every table can have a metatable associated with it, and this metatable can be accessed and modified using the setmetatable and getmetatable functions.

The setmetatable function sets the metatable of a table, while the getmetatable function retrieves the metatable of a table.


Setmetatable(table,metatable)

This method sets the metatable of a table. Here ‘table’ is the table whose metatable is to be set, and ‘metatable’ is the new metatable to be assigned to the table.

The following example illustrates the setmetatable() function in Lua:

Example: 

-- Define a table local myTable = { 2, 4, 6, 8, 10 }-- Define a metatable with custom behavior local myMetatable = { __tostring = function(t) return "This is myTable with values: " .. table.concat(t, ", ") end, __add = function(t1, t2) local result = {} for i = 1, #t1 do result[i] = t1[i] + t2[i] end return result end } -- Set the metatable for myTable setmetatable(myTable, myMetatable) -- Use the __toString metamethod print(myTable) local myOtherTable = { 1, 2, 3, 4, 5 } -- Use the __add metamethod to add two tables local sum = myTable + myOtherTable print('Values after using __add metamethod:',table.concat(sum, ", "))

Getmetatable(table)

This method gets the metatable of a table. The getmetatable() function takes a single argument, which is the table whose metatable we want to retrieve.
If the table has a metatable, getmetatable() returns it.
If the table does not have a metatable, getmetatable() returns nil.
Below example explains the usage of getmetatable() method:

Example: 

-- Define a table and a metatable local mytable = {a = 1, b = 2} local mymetatable = {c = 3, d = 4}-- Set the metatable for the table setmetatable(mytable, mymetatable)-- Get the metatable for the table local retrievedMetatable = getmetatable(mytable)if retrievedMetatable == mymetatable then print("Retrieved metatable is the same as the original metatable") else print("Retrieved metatable is NOT the same as the original metatable") end

Lua Meta Methods

Metamethods are special methods in Lua that are associated with metatables and define the behavior of operators and built-in functions when applied to tables.

In other words, metamethods provide a way to extend or modify the behavior of Lua’s built-in operators and functions when applied to tables.

Lua Metatables must first be created as regular tables before they can be used.

There are several metamethods in Lua, each corresponding to a specific built-in operator or function.

One or more of the following metamethods should be included in this table:

__index

Used when a non-existent key is used to index the table.

Here is an example that uses the __index metamethod:

Example: 

-- Define a table with some default values local myTable = { name = "John", age = 35, occupation = "Programmer" }-- Define a new table with a metatable that has an __index metamethod local myMetatable = { __index = function(table, key) if key == "gender" then return "Male" else return "Unknown" end end }-- Set the metatable for myTable to myMetatable setmetatable(myTable, myMetatable)-- Try to access a key that doesn't exist in myTable print(myTable.address) -- Output: Unknown-- Try to access the "gender" key that doesn't exist in myTable but specified using __index print(myTable.gender) -- Output: Male

__newindex

When a new index is set on a table, this function is called.

Below example examines the __newindex method in Lua:

Example: 

local mytable = {}local mymetatable = { __newindex = function (table, key, value) print("Assigning value " .. value .. " to key " .. key) end }setmetatable(mytable, mymetatable)mytable.name = "Harry"

__toString

This method allows us to define how an object should be converted to a string when it is printed.

This method is called by the tostring() function when it is called on an object.

Following example simplifies the understanding of the __toString method:

Example: 

local mytable = {name = "Harry", age = 35}local table_metatable = { __tostring = function(table) return "Name: " .. table.name .. ", Age: " .. table.age end }setmetatable(mytable, table_metatable)print(mytable)

__add

This function is called when two values are added.

Let’s explore an example where _add is implemented:

Example: 

local myTable = {value = 20}-- define a metatable with an __add metamethod local myMetatable = { __add = function(table1, table2) return {value = table1.value + table2.value} end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 5 local anotherTable = {value = 5}-- add the two tables together local result = myTable + anotherTable-- print the result print(result.value)

__sub

This method triggers when two values are subtracted with the operator.

Below example showcases the implementation of __sub metamethod in Lua:

Example: 

local myTable = {value = 20}-- define a metatable with a __sub metamethod local myMetatable = { __sub = function(table1, table2) return {value = table1.value – table2.value} end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 5 local anotherTable = {value = 5}-- subtract the two tables local result = myTable – anotherTable-- print the result print(result.value)

__mul

This method is invoked when two values are multiplied using the * operator.

The following example provides an overview of the __mul metamethod in Lua:

Example: 

local myTable = {value = 20}-- define a metatable with a __mul metamethod local myMetatable = { __mul = function(table1, table2) return {value = table1.value * table2.value} end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 5 local anotherTable = {value = 5}-- multiply the two tables together local result = myTable * anotherTable-- print the result print(result.value)

__div

This method is called if two values are divided using a / operator.

The __div method is demonstrated in the example below:

Example: 

local myTable = {value = 20}-- define a metatable with a __div metamethod local myMetatable = { __div = function(table1, table2) return {value = table1.value / table2.value} end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 5 local anotherTable = {value = 5}-- divide the two tables local result = myTable / anotherTable-- print the result print(result.value)

__mod

Used when two values are divided using the % operator.

The following example implements the __mod metamethod in Lua:

Example: 

local myTable = {value = 20}-- define a metatable with a __mod metamethod local myMetatable = { __mod = function(table1, table2) return {value = table1.value % table2.value} end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 5 local anotherTable = {value = 5}-- perform mod operation between the two tables local result = myTable % anotherTable-- print the result print(result.value)

__pow

This function is called when one value is raised to the power of another using the ^ operator.

Let’s understand the __pow metamethod using an example:

Example: 

local myTable = {value = 20}-- define a metatable with a __pow metamethod local myMetatable = { __pow = function(table1, table2) return {value = table1.value ^ table2.value} end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 5 local anotherTable = {value = 5}-- perform exponentiation operation between the two tables local result = myTable ^ anotherTable-- print the result print(result.value)

__unm

This function is invoked when a value is negated using the operator.

Now let’s explore the __unm metamethod using an example:

Example: 

local myTable = {value = 20}-- define a metatable with a __unm metamethod local myMetatable = { __unm = function(table1, table2) return {value = -table1.value} end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- perform unary minus operation on table1 local result = -myTable-- print the result print(result.value)

__eq

Triggered when two values are compared using the == operator.

Below example explains further the __eq metamethod in Lua:

Example: 

local myTable = {value = 20}-- define a metatable with an __eq metamethod local myMetatable = { __eq = function(table1, table2) return table1.value == table2.value end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 20 local anotherTable = {value = 20}-- Equality comparison between the two tables local result = myTable == anotherTable-- print the result print(result)

__lt

Executed when two values are compared using the < operator.

Using this example, the __lt metamethod in Lua is implemented:

Example: 

local myTable = {value = 20}-- define a metatable with a __lt metamethod local myMetatable = { __lt = function(table1, table2) return table1.value < table2.value end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 30 local anotherTable = {value = 30}-- Less than comparison between tables local result = myTable < anotherTable-- print the result print(result)

__le

When two values are compared using the <= operator, this function is called.

This example is used to examine the __le metamethod in Lua:

Example: 

local myTable = {value = 20}-- define a metatable with an __le metamethod local myMetatable = { __le = function(table1, table2) return table1.value <= table2.value end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- define another table with a value of 25 local anotherTable = {value = 25}-- Less than or equal to comparison between tables local result = myTable <= anotherTable-- print the result print(result)

__call

This method gets invoked when a table is called like a function.
Below example utilizes the __call metamethod in Lua:

Example: 

-- create a table local myTable = {}-- define a metatable for myTable with an __call metamethod local myMetatable = { __call = function(name) local str = "Hello John" return str end }-- set the metatable of myTable to myMetatable setmetatable(myTable, myMetatable)-- call myTable as a function local result = myTable()-- print the result print(result) -- should print "Hello John" to the console

Lua Metatables Benefits

Lua Metatables provide several benefits, including:

  • Metatables allow you to customize the behavior of tables in Lua. This can be used to implement various programming paradigms, such as object-oriented programming, or to add custom functionality to tables.
  • By defining metatables, you can reuse the same code across multiple tables, rather than writing the same code repeatedly.
  • Lua metatables allows you to extend the functionality of Lua’s built-in types, such as tables and numbers. This can be useful when working with complex data structures or when implementing domain-specific functionality.
  • Lua metatables can be used to provide a layer of security to Lua programs, by preventing access to certain methods or properties of tables.
  • Lua metatables can be used to optimize the performance of Lua programs, by providing custom implementations of common operations, such as indexing and arithmetic operations.
We value your feedback.
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0

Subscribe To Our Newsletter
Enter your email to receive a weekly round-up of our best posts. Learn more!
icon

Leave a Reply

Your email address will not be published. Required fields are marked *