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.

Advertisements