
- 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 with Lists
Metatables in Lua is a powerful mechanism to modify the default behaviours of tables. When we use table to represent a list, we can use metatables to define custom operations to lists.
Custom Indexing − We can define custom behavior while handling elements, like handling out of bound conditions, get a different default value instead of nil etc.
Operator Overloading − We can define standard operators like +, - , * , .. , = to work seemlessly with lists as these are working with strings.
Custom Length Handling − We can control how to decide length of the list especially in case of sparse lists.
-
Read Only − We can make a read only list where no new insertion/updation is allowed to the list.
Setting a Metatable for a list
As a first step, we create a list using a table.
local list = {"apple", "banana", "mango"}
Then we create another table to act as a metatable and associate with the list using setmetatable() method.
local listMetatable = {} setmetatable(list, listMetatable)
Now we can add metamethods to define the custom behavior of the list.
Example - Using __index() method to handle non-existing key
__index(table, key) metamethod is called when we're trying to use a key which is not assigned in the table. We've implement this method to return a default value for out of bound indices.
main.lua
-- list of numbers local numbersList = { 20, 10, 30, 40 } -- metatable to define default values local metatableDefault = { __index = function(table, key) if type(key) == "number" and (key < 1 or key > #table) then return "out of bounds" else -- standard default value return nil end end } -- set the metatable setmetatable(numbersList, metatableDefault) -- prints 30 print(numbersList[2]) -- prints out of bounds print(numbersList[0]) -- prints nil print(numbersList["a"])
Output
When the above code is built and executed, it produces the following result −
10 out of bounds nil
Explanation
numbersList is the list implemented as a table.
metatableDefault is a metatable with a metamethod __index() defined.
(key < 1 or key > #table) check is to see if index is out of range and then a default value "out of bounds" instead of default nil value.
If key is not a number, then we're returning nil as standard default value.
setmetatable(numbersList, metatableDefault) is used to set the metatable on numbersList.
numbersList[2] returns value at key 2 as table by default uses numeric indexes starting from 1.
numbersList[0] returns "out of bounds" (returned by __index() method) as 0 is a numeric key and is not present in our numbersList list .
numbersList["a"] returns nil as "a" is a non-numeric key and is not present in our numbersList list and __index() method returns nil for it.
Important Metamethods
Following are examples of important usage of metamethods to perform custom operations on Lists.
Using __newindex() method to make a readonly list
Using __len() method to handle length of list
Using __concat() method to concatenate lists using .. operator.
Using __eq() method to compare lists using == operator.
Using multiple metamethods for a list.