Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Lua iterator


May 12, 2021 Lua


Table of contents


Lua iterator

An iterator is an object that can be used to traverse some or all of the elements in a standard template library container, each representing a defined address in the container

In Lua, an iterator is a structure that supports pointer types and can traverse every element of a collection.


Generic for iterator

Generic for saves iterative functions within itself, and in fact it holds three values: iterative functions, state constants, and control variables.

The generic for iterator provides the key/value pair of the collection in the following syntax format:

for k, v in pairs(t) do
    print(k, v)
end

In the code above, k, v is the list of variables, and pairs(t) is the list of expressions.

See the following examples:

array = {"Lua", "Tutorial"}

for key,value in ipairs(array) 
do
   print(key, value)
end

The above code executes the output as follows:

1  Lua
2  Tutorial

In the above example, we used the iterative function ipairs provided by Lua by default.

Let's take a look at the execution of the paradigm for:

  • First, initialize and evaluate the value of the expression after in, which should return the three values required for the paradigm for: iterative functions, state constants, control variables, and, like multi-value assignments, if the expression returns fewer than three results that are automatically filled with nil, the multiple parts are ignored.
  • Second, the state constant and the control variable are called as arguments to the iterative function (note: for the for structure, the state constant is useless, only getting his value at initialization and passing it to the iterative function).
  • Third, assign the value returned by the iterative function to the list of variables.
  • Fourth, if the first value returned is the end of the nil loop, otherwise the loop body is executed.
  • Fifth, go back to the second step and call the iteration function again

。 I n Lua we often use functions to describe iterators, and each time we call the function we return the next element of the collection. Lua's iterators contain two types:

  • Stateless iterator
  • A multi-state iterator

Stateless iterator

Stateless iterators are iterators that do not retain any state, so in a loop we can use stateless iterators to avoid the additional cost of creating closures.

In each iteration, the iterative function is called as an argument with the values of two variables (state constants and control variables), and a stateless iterator uses only between these two values to get the next element.

A typical simple example of this stateless iterator is ipales, which traverses every element of the array.

In the following example, we use a simple function to implement the iterator, which implements the square of the number n:

function square(iteratorMaxCount,currentNumber)
   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
   return currentNumber, currentNumber*currentNumber
   end
end

for i,n in square,3,0
do
   print(i,n)
end

The output of the above examples is:

1	1
2	4
3	9

The state of the iteration includes the table being traversed (the state constant that does not change during the loop) and the current index subsector (control variable), both ipairs and iterative functions are simple, as we can do in Lua:

function iter (a, i)
    i = i + 1
    local v = a[i]
    if v then
       return i, v
    end
end
 
function ipairs (a)
    return iter, a, 0
end

When Lua calls ipails(a) to start the loop, he gets three values: the iteration function iterator, the state constant a, and the control variable initial value 0; until the first nil element.


A multi-state iterator

In many cases, the iterator needs to save multiple state information instead of simple state constants and control variables, the easiest way is to use closure, and one way is to encapsulate all the state information into the table and use the table as the state constant of the iterator, because in this case all the information can be stored within the table, so the iterative function usually does not need a second argument.

Here's an example of us creating our own iterator:

array = {"Lua", "Tutorial"}

function elementIterator (collection)
   local index = 0
   local count = #collection
   -- 闭包函数
   return function ()
      index = index + 1
      if index <= count
      then
         --  返回迭代器的当前元素
         return collection[index]
      end
   end
end

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

The output of the above examples is:

Lua
Tutorial

As we can see in the above example, the closure function is used within elementIterator to calculate the size of the collection and output individual elements.