English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Iterator (iterator) is an object that can be used to traverse part or all of the elements in the standard template library container, each iterator object represents a fixed address in the container.
In Lua, an iterator is a structure that supports pointer types, which can traverse each element of the collection.
The generic for iterator internally saves the iteration function, actually it saves three values: iteration function, status constant, control variable.
The generic for iterator provides the collection's key/The value pair, the syntax format is as follows:
for k, v in pairs(t) do print(k, v) end
In the above code, k, v are variable lists; pairs(t) is an expression list.
Check the following examples:
array = {"Google", "w3codebox} for key, value in ipairs(array) do print(key, value) end
The output result of the above code is:
1 Google 2 w3codebox
In the above example, we used the default iteration function ipairs provided by Lua.
Let's take a look at the execution process of the generic for:
First, initialization, calculate the value of the expression after in, the expression should return three values required by the generic for: iteration function, state constant, control variable; like multi-value assignment, if the number of returned results from the expression is less than three, it will be automatically supplemented with nil, and the extra part will be ignored.
Second, call the iteration function with the state constant and control variable as parameters (note: for the for structure, the state constant is not useful, it is only used to get its value and pass it to the iteration function during initialization).
Third, assign the values returned by the iteration function to a variable list.
Fourth, if the first returned value is nil, the loop ends, otherwise, execute the loop body.
Fifth, call the iteration function again at step two
In Lua, we often use functions to describe iterators, and each call to the function returns the next element of the set. Lua iterators include the following two types:
Stateless iterator
Multi-state iterators
A stateless iterator is an iterator that does not retain any state, so we can use a stateless iterator in a loop to avoid the extra cost of creating a closure.
For each iteration, the iteration function is called with the values of two variables (a constant state and a control variable) as parameters, and a stateless iterator can use these two values to obtain the next element.
A typical simple example of a stateless iterator is ipairs, which traverses each element of an array.
In the following example, we use a simple function to implement an iterator to calculate the square of a 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 result of the above example is:
1 1 2 4 3 9
The state of iteration includes the table being traversed (a constant state that does not change during the loop process) and the current index (a control variable), the ipairs and iteration functions are very simple, and we can implement them in Lua as follows:
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 ipairs(a) to start the loop, it gets three values: the iteration function iter, the state constant a, and the control variable initial value 0; then Lua calls iter(a,0) to return 1, a[1] (unless a[1=nil); The second iteration calls iter(a,1) return 2, a[2...... until the first nil element.
In many cases, iterators need to save multiple state information rather than simple state constants and control variables. The simplest method is to use closures, and another method is to encapsulate all state information into a table, using the table as the iterator's state constant. Because all information can be stored in the table in this case, the iteration function usually does not need a second parameter.
In the following example, we create our own iterator:
array = {"Google", "w3codebox} function elementIterator(collection) local index = 0 local count = #collection -- Closure Function 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
The output result of the above example is:
Google w3codebox
In the above examples, we can see that the closure function is used inside elementIterator to calculate the size of the collection and output each element.