Lua - Stateful Iterators



Stateful iterator as opposed to stateless iterator can hold the state of the current element using closures. Closure is a special function defined within a function which can read local variables to retain state of the function. To create a closure, we're going to create following two functions:

  • clousure function− internal function which can read local variables of outer function.

  • factory function− outer function containing state of the iterator.

Example - Custom Stateful Iterator with for loop

Let us now see an example of creating our own stateful iterator using a simple function that prints the elements of the collection.

elementIterator function is a stateful iterator and is accepting an array. First we're initializing the index as 0 as default state, then size of array is computed using # operator. As next, a closure function is created which is incrementing the index. Checking the index less than size of the array, current element is returned.

main.lua

-- Initialize an array
array = {"Lua", "Tutorial"}

-- return a stateful iterator to get values of collection passed
function elementIterator (collection)

   local index = 0
   local count = #collection
	
   -- The closure function is returned
	
   return function ()
      index = index + 1
		
      if index <= count
      then
         -- return the current element of the iterator
         return collection[index]
      end		
   end	
end

for element in elementIterator(array)
do
   print(element)
end

Output

When we run the above program, we will get the following output−

Lua
Tutorial

Here our stateful iterator is ignoring the control variable passed by for loop and maintaining the index itself.

Example - Custom Stateful Iterator with while loop

Let us now see an example of creating our own stateful iterator using a simple function that prints the elements of the collection using while loop.

main.lua

-- Initialize an array
array = {1, 2, 3, 4, 5, 6}

-- return a stateful iterator to get values of collection passed
function elementIterator (collection)

   local index = 0
   local count = #collection
	
   -- The closure function is returned
	
   return function ()
      index = index + 1
		
      if index <= count
      then
         -- return the current element of the iterator
         return collection[index]
      end		
   end	
end

-- get the iterator on the iterator
local iterator = elementIterator(array)

-- loop through the iterator
while true
do
   -- call the iterator
   local element = iterator()
   -- if element is nil, stop the iterator 
   if element == nil
   then
      break end   
   -- print the element
   print(element)
end

Output

When we run the above program, we will get the following output−

1
2
3
4
5
6

Here our stateful iterator is ignoring the control variable passed by for loop and maintaining the index itself.

Advertisements