Iterator Pattern
Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 64 of 70.
When you have a collection of items stored inside an object, you often want to loop through them. Lua's generic for loop works beautifully with custom iterators, and you can build this functionality directly into your classes.
The Iterator pattern lets an object control how its internal data is traversed. One elegant approach uses the __call metamethod, which makes an object callable like a function. Each call returns the next item until there are no more.
local Collection = {}
Collection.__index = Collection
function Collection:new()
local obj = { items = {}, index = 0 }
setmetatable(obj, Collection)
return obj
end
function Collection:add(item)
table.insert(self.items, item)
end
function Collection:__call()
self.index = self.index + 1
return self.items[self.index]
end
With __call defined, you can iterate using a while loop or pass the object directly to a generic for:
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag do
print(item)
end
The loop calls bag() repeatedly. When __call returns nil (no more items), the loop stops. This pattern encapsulates iteration logic inside the object itself, giving you full control over how—and in what order—items are accessed.
Challenge
EasyLet's build a Playlist class that you can iterate through using Lua's generic for loop! You'll implement the Iterator pattern using the __call metamethod, allowing your playlist to be traversed song by song.
You'll organize your code across two files:
Playlist.lua: Create a Playlist class that stores songs internally. Your class needs a:new()constructor that initializes an empty songs list and sets the iteration index to 0. Add an:addSong(title)method to add songs to the playlist. Most importantly, implement the__callmetamethod so that each time the playlist is "called," it returns the next song in the list (ornilwhen there are no more songs).main.lua: Require your Playlist module and create a new playlist. Add songs to it based on the inputs you receive, then use a genericforloop to iterate through the playlist and print each song title on its own line.
The magic of the Iterator pattern is that your Playlist object becomes callable—when used in a for loop, Lua calls it repeatedly until it returns nil, giving you each song in sequence.
You will receive three inputs, each representing a song title to add to your playlist (in order).
For example, if the inputs are Bohemian Rhapsody, Stairway to Heaven, and Hotel California, the output should be:
Bohemian Rhapsody
Stairway to Heaven
Hotel CaliforniaIf the inputs are Yesterday, Imagine, and Let It Be, the output should be:
Yesterday
Imagine
Let It BeCheat sheet
The Iterator pattern allows an object to control how its internal data is traversed by implementing custom iteration logic.
Use the __call metamethod to make an object callable like a function. Each call returns the next item until there are no more (returns nil):
local Collection = {}
Collection.__index = Collection
function Collection:new()
local obj = { items = {}, index = 0 }
setmetatable(obj, Collection)
return obj
end
function Collection:add(item)
table.insert(self.items, item)
end
function Collection:__call()
self.index = self.index + 1
return self.items[self.index]
end
With __call defined, you can use the object directly in a generic for loop:
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag do
print(item)
end
The loop calls the object repeatedly. When __call returns nil, the loop stops automatically.
Try it yourself
-- Require the Playlist module
local Playlist = require('Playlist')
-- Read three song titles from input
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()
-- TODO: Create a new playlist using Playlist:new()
-- TODO: Add the three songs to the playlist using :addSong()
-- TODO: Use a generic for loop to iterate through the playlist
-- and print each song title on its own line
-- Hint: for song in playlist do ... end
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1The 'Self' Concept
Tables with FunctionsExplicit 'self'The Colon SyntaxDot vs ColonRecap - Moving Point4Project: Digital Bank
Project SetupDeposit Method7Polymorphism & Overriding
Overriding MethodsCalling Parent MethodsDuck TypingCommon InterfaceChecking TypeRecap - Employee Roles10Project: Shape Manager
Project SetupRectangle Class2Class Prototype Pattern
The Prototype ConceptLinking with __indexThe :new() ConstructorInitializing AttributesIndependent InstancesRecap - Car Factory5Operator Overloading in OOP
Adding ObjectsSubtracting ObjectsConcatenating ObjectsComparing Objects (<, >)Recap - Wallet Math8Encapsulation
Naming ConventionsClosures for PrivacyAccess via ClosuresRead-Only TablesValidation LogicRecap - Secure Vault11Design Patterns (Lite)
Factory FunctionsSingleton TableIterator PatternObserver (Listener)Recap - Logger Factory3Object State and Behavior
Instance VariablesGetter MethodsSetter MethodsCalculated PropertiesFormatting StringsEquality ChecksRecap - Student Grade6Inheritance Basics
The Inheritance SetupInheriting MethodsExtending the ConstructorAdding Child MethodsShared vs UniqueRecap - Shape Hierarchy