← Back to the index page

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:

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.

← Back to the index page