
- Lua Tutorial
- Lua - Home
- Lua Basics
- Lua - Overview
- Lua - Environment
- Lua - Basic Syntax
- Lua - Comments
- Lua - Print Hello World
- Lua - Variables
- Lua - Data Types
- Lua - Operators
- Lua - Loops
- Lua - Generic For
- Lua - Decision Making
- Lua - Date and Time
- Lua Functions
- Lua - Functions
- Lua - Multiple Results
- Lua - Named Arguments
- Lua - Default/Optional Arguments
- Lua - Closures
- Lua - Uses of Closures
- Lua - Local Functions
- Lua - Anonymous Functions
- Lua - Functions in Table
- Lua - Proper Tail Calls
- Lua Strings
- Lua - Strings
- Lua - String Concatenation
- Lua - Loop Through String
- Lua - String to Int
- Lua - Split String
- Lua - Check String is NULL
- Lua Arrays
- Lua - Arrays
- Lua - Multi-dimensional Arrays
- Lua - Array Length
- Lua - Iterating Over Arrays
- Lua - Slicing Arrays
- Lua - Sorting Arrays
- Lua - Merging Arrays
- Lua - Sparse Arrays
- Lua - Searching Arrays
- Lua - Resizing Arrays
- Lua - Array to String Conversion
- Lua - Array as Stack
- Lua - Array as Queue
- Lua - Array with Metatables
- Lua - Immutable Arrays
- Lua - Shuffling Arrays
- Lua Iterators
- Lua - Iterators
- Lua - Stateless Iterators
- Lua - Stateful Iterators
- Lua - Built-in Iterators
- Lua - Custom Iterators
- Lua - Iterator Closures
- Lua - Infinite Iterators
- Lua - File Iterators
- Lua - Table Iterators
- Lua - Numeric Iterators
- Lua - Reverse Iterators
- Lua - Filter Iterators
- Lua - Range Iterators
- Lua - Chaining Iterators
- Lua Tables
- Lua - Tables
- Lua - Tables as Arrays
- Lua - Tables as Dictionaries
- Lua - Tables as Sets
- Lua - Table Length
- Lua - Table Iteration
- Lua - Table Constructors
- Lua - Loop through Table
- Lua - Merge Tables
- Lua - Nested Tables
- Lua - Accessing Table Fields
- Lua - Copy Table by Value
- Lua - Get Entries from Table
- Lua - Table Metatables
- Lua - Tables as Objects
- Lua - Table Inheritance
- Lua - Table Cloning
- Lua - Table Sorting
- Lua - Table Searching
- Lua - Table Serialization
- Lua - Weak Tables
- Lua - Table Memory Management
- Lua - Tables as Stacks
- Lua - Tables as Queues
- Lua - Sparse Tables
- Lua Lists
- Lua - Lists
- Lua - Inserting Elements into Lists
- Lua - Removing Elements from Lists
- Lua - Iterating Over Lists
- Lua - Reverse Iterating Over Lists
- Lua - Accessing List Elements
- Lua - Modifying List Elements
- Lua - List Length
- Lua - Concatenate Lists
- Lua - Slicing Lists
- Lua - Sorting Lists
- Lua - Reversing Lists
- Lua - Searching in Lists
- Lua - Shuffling List
- Lua - Multi-dimensional Lists
- Lua - Sparse Lists
- Lua - Lists as Stacks
- Lua - Lists as Queues
- Lua - Functional Operations on Lists
- Lua - Immutable Lists
- Lua - List Serialization
- Lua - Metatables with Lists
- Lua Modules
- Lua - Modules
- Lua - Returning Functions from Modules
- Lua - Returning Functions Table from Modules
- Lua - Module Scope
- Lua - SubModule
- Lua - Module Caching
- Lua - Custom Module Loaders
- Lua - Namespaces
- Lua - Singleton Modules
- Lua - Sharing State Between Modules
- Lua - Module Versioning
- Lua Metatables
- Lua - Metatables
- Lua - Chaining Metatables
- Lua Coroutines
- Lua - Coroutines
- Lua File Handling
- Lua - File I/O
- Lua - Opening Files
- Lua - Modes for File Access
- Lua - Reading Files
- Lua - Writing Files
- Lua - Closing Files
- Lua - Renaming Files
- Lua - Deleting Files
- Lua - File Buffers and Flushing
- Lua - Reading Files Line by Line
- Lua - Binary File Handling
- Lua - File Positioning
- Lua - Appending to Files
- Lua - Error Handling in File Operations
- Lua - Checking if File exists
- Lua - Checking if File is Readable
- Lua - Checking if File is Writable
- Lua - Checking if File is ReadOnly
- Lua - File Descriptors
- Lua - Creating Temporary Files
- Lua - Working with Large Files
- Lua Advanced
- Lua - Error Handling
- Lua - Debugging
- Lua - Garbage Collection
- Lua - Object Oriented
- Lua - Web Programming
- Lua - Database Access
- Lua - Game Programing
- Lua Useful Resources
- Lua - Quick Guide
- Lua - Useful Resources
- Lua - Discussion
Lua - Metatables
A metatable is a table that helps in modifying the behavior of a table it is attached to 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.
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 meta method
A simple example of metatable for looking up the meta table when it's not available in table is shown below.
main.lua
-- set the metatable mytable = setmetatable({key1 = "value1"}, { __index = function(mytable, key) -- if key2 is used, then return metatablevalue if key == "key2" then return "metatablevalue" else return nil end end }) -- print metatable details print(mytable.key1, mytable.key2)
Output
When we run the above program, we will get the following output−
value1 metatablevalue
Let us explain what happened in the above example in steps.
The table mytable here is {key1 = "value1"}.
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 "key2", if it's found, it returns "metatablevalue", otherwise returns mytable's value for corresponding index.
We can have a simplified version of the above program as shown below.
mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } }) print(mytable.key1,mytable.key2)
Example - Using __newindex meta method
When we add __newindex to metatable, if keys are not available in the table, the behavior of new keys will be defined by meta methods. A simple example where metatable's index is set when index is not available in the main table is given below.
main.lua
-- define a table mymetatable = {} -- set metatable mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable }) -- print key1 print(mytable.key1) -- set the new key and print mytable.newkey = "new value 2" print(mytable.newkey,mymetatable.newkey) -- update the key1 and print mytable.key1 = "new value 1" print(mytable.key1,mymetatable.newkey1)
Output
When you run the above program, you get the following output−
value1 nil new value 2 new value 1 nil
You can see in the above program, if a key exists in the main table, it just updates it. When a key is not available in the maintable, it adds that key to the metatable.
Example - Update Table
Another example that updates the same table using rawset function is shown below.
main.lua
-- create a new metatable mytable = setmetatable({key1 = "value1"}, { -- create a new function using rawset __newindex = function(mytable, key, value) rawset(mytable, key, "\""..value.."\"") end }) -- update value of key1 mytable.key1 = "new value" -- set value of key2 mytable.key2 = 4 -- print key1 and key2 print(mytable.key1,mytable.key2)
Output
When we run the above program we will get the following output−
new value "4"
rawset sets value without using __newindex of metatable. Similarly there is rawget that gets value without using __index.
Example - Adding Operator Behavior to Tables
A simple example to combine two tables using + operator is shown below −
main.lua
-- define a maxn function to compute max from an array table.maxn = function( tableObject ) local maxIndex = 0 for k, _ in pairs( tableObject ) do maxIndex = math.max( maxIndex, k ) end return maxIndex end -- create a metatable to insert max mytable = setmetatable({ 1, 2, 3 }, { __add = function(mytable, newtable) for i = 1, table.maxn(newtable) do table.insert(mytable, table.maxn(mytable)+1,newtable[i]) end return mytable end }) -- create another table secondtable = {4,5,6} -- add the tables mytable = mytable + secondtable -- iterate and print updated table for k,v in ipairs(mytable) do print(k,v) end
Output
When we run the above program, we will get the following output−
1 1 2 2 3 3 4 4 5 5 6 6
The __add key is included in the metatable to add behavior of operator +. The table of keys and corresponding operator is shown below.
Sr.No. | Mode & Description |
---|---|
1 |
__add Changes the behavior of operator '+'. |
2 |
__sub Changes the behavior of operator '-'. |
3 |
__mul Changes the behavior of operator '*'. |
4 |
__div Changes the behavior of operator '/'. |
5 |
__mod Changes the behavior of operator '%'. |
6 |
__unm Changes the behavior of operator '-'. |
7 |
__concat Changes the behavior of operator '..'. |
8 |
__eq Changes the behavior of operator '=='. |
9 |
__lt Changes the behavior of operator '<'. |
10 |
__le Changes the behavior of operator '<='. |
Example - Using __call meta method
Adding behavior of method call is done using __call statement. A simple example that returns the sum of values in main table with the passed table.
main.lua
-- define a maxn function to compute max from an array table.maxn = function( tableObject ) local maxIndex = 0 for k, _ in pairs( tableObject ) do maxIndex = math.max( maxIndex, k ) end return maxIndex end -- create the metatable using call method mytable = setmetatable({10}, { __call = function(mytable, newtable) sum = 0 -- compute sum of each entry for i = 1, table.maxn(mytable) do sum = sum + mytable[i] end -- compute sum of each entry for i = 1, table.maxn(newtable) do sum = sum + newtable[i] end return sum end }) -- create the table newtable = {10,20,30} -- create a new table using metatable print(mytable(newtable))
Output
When we run the above program, we will get the following output−
70
Example - Using __tostring meta method
To change the behavior of the print statement, we can use the __tostring metamethod. A simple example is shown below.
main.lua
-- create a new metatable to get sum of elements of the main table mytable = setmetatable({ 10, 20, 30 }, { __tostring = function(mytable) sum = 0 for k, v in pairs(mytable) do sum = sum + v end return "The sum of values in the table is " .. sum end }) print(mytable)
Output
When we run the above program, we will get the following output−
The sum of values in the table is 60
If you know the capabilities of meta table fully, you can really perform a lot of operations that would be very complex without using it. So, try to work more on using metatables with different options available in meta tables as explained in the samples and also create your own samples.