Custom Luau Iterators!

Hello, my name is PostVivic. The purpose of this devforum post is to explain what an “iterator” is in Luau. There is documentation in the Lua docs, but afaik Roblox doesn’t have any documentation on this. Apologies for terrible formatting, This is my first devforum tutorial and I don’t know how to format yet.

If i’m being honest, iterators aren’t very useful for everyday developers. But it’s an interesting lower level concept that helps you understand under the hood of some methods like pairs(), ipairs(), and string.gmatch().

Getting our understanding of iterators

basic explaination

For the purposes of this section, i’m going to refer to an Iterator as a function that is called repeatedly in a for loop, that determines the for loop’s logic.

Lets give an example of a basic iterator to see what it is

local x = 3
function Iterator()
	if x <= 0 then return nil end
	x -= 1

	return x
end

for y in Iterator do
	print(y)
end

This basic iterator counts down from 3, but why? Whenever you put a function in a for loop, it repeatedly runs that function until the function returns nil. any returned values are output in the for loop itself. In this case, the function returns nil when x is less than or equal to zero and each iteration of the function takes one away from X

image

Applying it to larger scales

advanced stuffs

There’s one main issue with the way our iterator was set up in the basic explaination, you can’t run it more than once. This is because x is essentially a global variable and is used throughout every for loop call!

How do we fix this to make it able to be used multiple times? Simply wrap it in its own special scope of course! This is the main format for an iterator you would see through the Lua documentation.

function Iterator()
	local x = 3
	return function()
		if x <= 0 then return end
		x -= 1
		
		return x
	end
end

for y in Iterator() do
	
end

Notice when we use the iterator now, we call the Iterator method, this “constructs” a new function with its own secluded scope!

Now we need to adjust our vocabulary to align with the Lua docs, since there’s two functions, there’s two names.
An “iterator” is the function that constructs a “closure”
A “closure” is the function that actually repeats in a for loop

Endnotes

Endnotes

The main usage for this knowledge is to give your library, as Elttob would call it, “Syntactic Sugar”

However the use cases of this are limited, due to the fact that roblox gives higher level ways to iterate using for loops, like dictionary iteration without pairs.

One example I could think of is looping through pixels with roblox’s EditableImage api, as the ReadPixels and WritePixels have data in a pretty weird way

for r, g, b, a in Pixels(EditableImage) do
	
end

Also if you look under the hood of the “ipairs” iterator it will look something like this

function ipairs(tbl)
	local i = 0
	return function()
		i += 1
		return tbl[i]
	end
end
5 Likes