Lua - Uses of Closures
A closure function is an inner function which closes over local variable of the enclosing function. A closure is a powerful mechanism in Lua. In this chapter, we're discussing various scenarios and usage of closures.
Iterator
We can create custom iterators to navigate colletions using closures. Generic for loop uses iterator to traverse collection and iterating state is maintained within the closure.
main.lua
function listIterator(list)
local i = 0
local n = #list -- size of the list
-- closure function to get next element
return function()
i = i + 1
if i <= n then return list[i] end
end
end
list = {'A', 'B', 'C', 'D', 'E'}
for element in listIterator(list) do
print(element)
end
Output
When the above code is built and executed, it produces the following result −
A B C D E
Encapsulation
Using enclosure, we can implement encapsulation in Lua similar to private variable in object oriented languages, by keeping data within scope of a function and modification to data is possible through returned closure.
main.lua
function newAccount(balance)
local account = {}
-- closure to add amount to balance
account.deposit = function(amount)
balance = balance + amount
return balance
end
-- closure to deduct amount to balance
account.withdraw = function(amount)
balance = balance - amount
return balance
end
-- closure to get updated balance
account.getBalance = function()
return balance
end
return account
end
-- create an account, with balance 100
account = newAccount(100)
-- add 50 to the balance and print the updated balance as 150
print(account.deposit(50))
-- get updated balance 150
-- balance is not accessible via any other means
print(account.getBalance())
Output
When the above code is built and executed, it produces the following result −
150 150
High Order Functions
While defining a higher order function which can take a function as argument or return a function. A closure plays an important role. A closure allows to retain context of the passed or returned function.
main.lua
function multiplyBy(factor)
return function(x)
return x * factor
end
end
double = multiplyBy(2)
triple = multiplyBy(3)
-- prints 10
print(double(5))
-- prints 15
print(triple(5))
Output
When the above code is built and executed, it produces the following result −
10 15
Callback functions
In event driven programming, during an event or in asynchronous method calls, a closure can be used as a callback function which can access the data of the enviroment where callback function is created.
Factory Functions
Using closures, we can create factory functions which can create new functions as shown in above example where multiplyBy() function is used to create multiple multiplier functions. Here closure helps in generating function which have specific behavior based on captured enviroment.
Module Implementation
We can create modules by encapsulating functions and data with local scope using closures and returns a set of functions which are publically accessible to work on data.
Summary
In essence, closure provides a powerful and flexible option in Lua programming to create functions which can carry surrounding context. This helps in functional programming, increasing expressiveness of the programming language.