Lua - Functional Operations on Lists
Functional Programming refers to a declarative programming model where the focus is on "What you are doing" instead of "How you are doing". In Lua, we can functional programming easily on lists by making custom codes. Following are few examples of commonly used functional programming constructs.
map− applies a given function on each element of the list and returns a table with updated values.
apply− applies a given function on each element of the list and updates its each value.
filter− filter element of the list based on given function and returns a table with filtered values.
concat− concatenate elements of each list
reverse−reverses the elements of the list
sort−sorts the elements of the list
Let's explore few functions by examples.
map function
Consider a case, where we've having a List of numbers and we want to get a table of squares of these numbers. Following implementation of map function will help in achieving the same.
-- map function to apply a function on a list
function map(f, list)
local squares = {}
-- get result of function on each element
-- and store in a table
for v in list:iterator() do
table.insert(squares, f(v[1]))
end
-- return the resulant table
return squares
end
Complete Example of Applying map function on a list
In following example, we'll apply the map function to get squares of each number of a list.
main.lua
-- List Implementation
list = {}
list.__index = list
setmetatable(list, { __call = function(_, ...)
local t = setmetatable({ length = 0 }, list)
for _, v in ipairs{...}
do t:push(v)
end
return t
end })
-- push an element to the end of the list
function list:push(t)
-- move till last node
if self.last then
self.last._next = t
t._prev = self.last
self.last = t
else
-- set the node as first node
self.first = t
self.last = t
end
-- increment the length of the list
self.length = self.length + 1
end
-- iterate through the list
local function iterate(self, current)
if not current then
current = self.first
elseif current then
current = current._next
end
return current
end
function list:iterator()
return iterate, self, nil
end
-- map function to apply a function on a list
function map(f, list)
local squares = {}
-- get result of function on each element
-- and store in a table
for v in list:iterator() do
table.insert(squares, f(v[1]))
end
-- return the resulant table
return squares
end
-- create a new list with values
local numbers = list({ 1 },{ 2 }, { 3 },{ 4 },{ 5 })
squares = map(function(n) return n*n end, numbers)
-- list of squares
for _,v in ipairs(squares) do
print(v)
end
Output
When we run the above code, we will get the following output−
1 4 9 16 25
apply function
Consider a case, where we've having a List of numbers and we want to update them to be squares of these numbers. Following implementation of apply function will help in achieving the same.
-- apply function to apply a function on a list
function apply(f, list)
-- apply function on each element
-- and update the value
for v in list:iterator() do
v[1] = f(v[1])
end
end
Complete Example of Applying apply function on a list
In following example, we'll use the apply function to make squares of each number of a list.
main.lua
-- List Implementation
list = {}
list.__index = list
setmetatable(list, { __call = function(_, ...)
local t = setmetatable({ length = 0 }, list)
for _, v in ipairs{...}
do t:push(v)
end
return t
end })
-- push an element to the end of the list
function list:push(t)
-- move till last node
if self.last then
self.last._next = t
t._prev = self.last
self.last = t
else
-- set the node as first node
self.first = t
self.last = t
end
-- increment the length of the list
self.length = self.length + 1
end
-- iterate through the list
local function iterate(self, current)
if not current then
current = self.first
elseif current then
current = current._next
end
return current
end
function list:iterator()
return iterate, self, nil
end
-- apply function to apply a function on a list
function apply(f, list)
-- apply function on each element
-- and update the value
for v in list:iterator() do
v[1] = f(v[1])
end
end
-- create a new list with values
local numbers = list({ 1 },{ 2 }, { 3 },{ 4 },{ 5 })
squares = apply(function(n) return n*n end, numbers)
-- list of squares
for v in numbers:iterator() do
print(v[1])
end
Output
When we run the above code, we will get the following output−
1 4 9 16 25
In the similar fashion, we can create any functional program over Lua list as shown in examples above.