Iterators
An iterator is any structure that enables traversal through the elements of a collection (table). In Lua, iterators are usually represented as functions that return the next element from the collection each time they are called. There are built-in iterators: pairs
and ipairs
. Under the hood pairs
and ipairs
iterators use next
function.
Generic for-loop¶
for <var-list> in <expr-list> do
<body>
end
Where:
- var-list: a comma-separated list of variable names available in the body;
- exp-list: a comma-separated list of expressions.
Simple iterator¶
for k, v in ipairs(list) do
print(k, v)
end
Can be rewritten without pairs
or iparis
iterator.
for k, v in next, list do
print(k, v)
end
Stateful iterator¶
Iterator that stores its state in itself (variable i
). This example has one drawback; it creates the closure (function) with each call at the cost of memory and CPU time. Notice that state can be stored not only in a single variable but also in table
if the more complex state is required.
Tip
Read more about Iterators with Complex State in the PIL book.
I would prefer to design software using stateless iterators or true iterators
local list = { 1, 2, 3, 4, 5 }
local function iterator10(t)
local i = 0
return function()
i = i + 1
if t[i] then
return i, t[i] * 10
end
end
end
for i, x in iterator10(list) do
print(i, x)
end
Stateless iterator¶
It is obvious from the name that this is the iterator that does not store its state. If possible, the stateless iterators are more preferable if performance matters.
local function iter(t, i)
i = i + 1
if t[i] then
return i, t[i] * 10
end
end
local function iterator10(t)
return iter, t, 0
end
for k, v in iterator10(list) do
print(k, v)
end
True iterator¶
Actually in Lua, functions do not iterate anything; only the for loop does the iteration. There is another way to create iterators. We can create a function which accepts list as the first argument, and callback function.
local function iterator10(t, callback)
for k, v in ipairs(t) do
callback(k, v)
end
end
iterator10(list, function(k, v)
print(k, v * 10)
end)
Coroutines as iterators¶
If you are not familiar with coroutines](/post/understanding-coroutines.html), I would like to recommend looking at my article “Understanding Coroutines in Lua”.
For heavy calculations, coroutines can be used as iterators. Here is a very trivial example from above, just iterating the simple list multiplied by 10
.
local function iter10(t)
local co = coroutine.create(function()
for _, x in ipairs(t) do
coroutine.yield(x)
end
end)
return function()
local _, x = coroutine.resume(co)
if x then
x = x * 10
end
return x
end
end
for x in iter10(list) do
print(x)
end
References¶
Feedback
For feedback, please check the contacts section. Before writing, please specify where you came from and who you are. Sometimes spammers go insane. Thank you in advance for your understanding.