Menu
Coddy logo textTech

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 icon

Challenge

Easy

Let'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 __call metamethod so that each time the playlist is "called," it returns the next song in the list (or nil when 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 generic for loop 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 California

If the inputs are Yesterday, Imagine, and Let It Be, the output should be:

Yesterday
Imagine
Let It Be

Cheat 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
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming