You are on page 1of 2

This first edition was written for Lua 5.0.

While still largely relevant for later versions, there are


some differences.
The fourth edition
targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.

Programming in Lua
Part I. The Language
Chapter 7. Iterators and the Generic for

7.5 – True Iterators


The name "iterator" is a little misleading,
because our iterators do not iterate:
What iterates is the for loop.
Iterators only provide the successive values for
the iteration.
Maybe a better name would be "generator",
but "iterator" is
already well established in other languages,
such as Java.

However, there is another way to build iterators


wherein iterators actually do
the iteration.
When we use such iterators we do not write a loop;
instead, we
simply call the iterator with an argument
that describes what the iterator
must do at each iteration.
More specifically,
the iterator receives as argument
a function that it calls
inside its loop.

As a concrete example,
let us rewrite once more the allwords iterator using
this style:

function allwords (f)

-- repeat for each line in the file

for l in io.lines() do

-- repeat for each word in the line

for w in string.gfind(l, "%w+") do

-- call the function

f(w)

end

end

end

To use such iterator, we must supply the loop body as a function.


If we only
want to print each word,
we simply use print:

allwords(print)

More often, we use an anonymous function as the body.


For instance, the next
code fragment counts how many times
the word "hello" appears in the input
file:
local count = 0

allwords(function (w)

if w == "hello" then count = count + 1 end

end)

print(count)

The same task, written with the previous iterator style,


is not very different:

local count = 0

for w in allwords() do

if w == "hello" then count = count + 1 end

end

print(count)

True iterators were popular in older versions of Lua,


when the language did
not have the for statement.
How do they compare with generator-style
iterators?
Both styles have approximately the same overhead:
one function
call per iteration.
On the one hand,
it is easier to write the iterator with this
second style
(although we can recover this easiness with coroutines).
On the
other hand,
the generator style is more flexible.
First, it allows two or more
parallel iterations.
(For instance, consider the problem of iterating over two
files
comparing them word by word.)
Second, it allows the use of break and
return inside
the iterator body.
(With a true iterator,
a return returns from
the anonymous function,
not from the function doing the iteration.)

Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved.

You might also like