Lua - Tables and Metatables



Lua provides an interesting option to modify the behavior of a table. For example, to get a default value in case key is not present in the table.

A metatable is another table which can modify the table behavior with the help of a key set and related meta methods. These meta methods are powerful Lua functionality that enables features like −

  • Changing/adding functionalities to operators on tables.

  • Looking up metatables when the key is not available in the table using __index in metatable.

There are two important methods that are used in handling metatables which includes −

  • setmetatable(table,metatable) − This method is used to set metatable for a table.

  • getmetatable(table) − This method is used to get metatable of a table.

Syntax - Setting MetaTable

Let's first look at how to set one table as metatable of another. It is shown below.

mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)

The above code can be represented in a single line as shown below.

mytable = setmetatable({},{})

Example - Using _index to get a default value in associated table

A simple example of metatable for looking up the meta table when it's not available in table is shown below.

main.lua

mapTable = {Mon="Monday", Tue="Tuesday", Wed="Wednesday"}

-- set the metatable
setmetatable(mapTable, {
   -- self represent the table on which metatable is applied
   -- index is the non-existing index
   __index = function(self, index)
	return "Not defined."
   end
})

-- print value using existing key
print(mapTable.Mon)

-- print value using non-exiting key
print(mapTable.Sun)

Output

When we run the above program, we will get the following output−

Monday
Not Defined

Let us explain what happened in the above example in steps.

  • The table mapTable here is {Mon="Monday", Tue="Tuesday", Wed="Wednesday"}.

  • Metatable is set for mytable that contains a function for __index, which we call as a metamethod.

  • The metamethod does a simple job of looking up for an index. If a non-existing index is passed to the table, then a default value of "Not defined." is returned, otherwise the corresponding value is printed.

Example - Using _index to get a default value in numerically indexed table

In case numerically index table as well, we can set and use metatable to change table behavior as shown below−

main.lua

numbers = { -1, -2, -3, -4, -5, -6}

-- set the metatable
setmetatable(numbers, {
   -- self represent the table on which metatable is applied
   -- index is the non-existing index
   __index = function(self, index)
	return math.random(10)
   end
})

-- print value using existing key
print(numbers[1])

-- print value using non-exiting key
print(numbers[7])

Output

When we run the above program, we will get the following output−

-1
2

Explanation

  • The table numbers is a numerically indexed table.

  • Metatable is set on numbers table that contains a function for __index, which we call as a metamethod.

  • The metamethod does a simple job of looking up for an index. If a non-existing index is passed to the table, then a random value is returned, otherwise the corresponding value is printed.

Advertisements