LUA / CHAPTER 10
Custom iterators and termination contracts
AdvancedExpose a traversal without exposing its storage representation.
By the end of this chapter
- Return successive values from an iterator closure
- Use nil as the termination signal
- Keep traversal state independent per iterator
The idea
A generic for loop repeatedly calls an iterator and stops when its first returned value is nil. A closure iterator can keep its position private while exposing one value at a time. This allows callers to traverse a computed sequence without knowing whether the implementation stores a table, calculates values, or reads from another source.
Choose a yielded shape whose first value cannot be confused with termination. If nil is valid data, yield a non-nil index first and put the data in a later result. Create a fresh iterator for independent traversals instead of reusing one exhausted stateful closure. Document when traversal completes and whether it owns resources that need cleanup after early termination.
local function stepper(limit)
local n=0
return function()
n=n+1
if n<=limit then return n*2 end
end
end
for value in stepper(3) do print(value) end2 4 6
Each call advances private state. Once the limit is exceeded, the iterator returns nil and the generic loop ends.
Try it yourself
Design an indexed iterator that can yield nil data values without ending early.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING