Before we start, don't be like this guy
In Lua, iterators are functions that return a closure (function). This closure is called each time the iterator is called, and it returns the next value in the iteration sequence. You may already know some iterator functions such as ipairs or pairs. If you print them out, you would observe that they return a closure.
print(pairs({})) -- output: function: address table: address nil
print(ipairs({})) -- output: function: address table: address 0
First, the function (next) is outputted, then the table inside the functions ({}), and then finally the starter index
To get started, you must first know what next is and what it does.
next is a function that is usually used to iterate over tables and returns the next key-value pair in a table following a given key. Key defaults to nil
next(Table, Key)
local my_table = {
[1] = "a",
[2] = "b",
[3] = "c"
}
print(next(my_table)) -- 1 a
print(next(my_table, 1)) -- 2 b
print(next(my_table, 2)) -- 3 c
print(next(my_table, 3)) -- nil
First, let's start making our own iterator function by recreating pairs We'll name our iterator function my_pairs From our previous test, we know that an iterator returns a function, a table, and a starter index. Let's use that to create a foundation for our script
local function my_pairs(mytable)
local index = nil
return function(mytable)
end, mytable, index
end
print(my_pairs({})) -- output: function: address table: address nil
Let's start working on our return function
As mentioned before, next returns the next key-value pair after you provide it a key (2nd parameter) Based off of that, lets add some code to our function.
local function my_pairs(mytable)
local index = nil
return function(mytable)
local key, value = next(mytable, index)
index = key
return key, value
end, mytable, index
end
Let's dissect what we wrote
local key, value = next(mytable, index)
Here, we use the next function to get the next key-value pair after index (nil) Then, we set the key-value pair to their respective variables.
index = key
We set the index to the key so after we loop back, we will start off with the new index
return key, value
We finally return the key value pair Refer to the note at the bottom if you are confused on why a while/for loop wasn't used to repeat the process
Let's apply it into a for loop
-- table
local my_table = {
[1] = "a",
[2] = "b",
[3] = "c"
}
-- iterator function
local function my_pairs(mytable)
local index = nil
return function(mytable)
local key, value = next(mytable, index)
index = key
return key, value
end, mytable, index
end
-- for loop
for i, v in my_pairs(my_table) do
print(i,v)
end
--[[
Output:
1 a
2 b
3 c
]]--
Note: If you are by any chance confused why I didn't use a loop in the my_pairs function, the for loop does that for us. The for loop repeats the process until the function returns nil (this isn't special to our custom function). Though while loops can also be used to loop over a table using next, example below
-- table
local my_table = {
[1] = "a",
[2] = "b",
[3] = "c"
}
local function my_for(myTable, func)
local index = nil
while true do
local key, value = next(myTable, index)
if not key then break end;
index = key
func(key, value)
end
end
my_for(my_table, function(a,b) print(a,b) end)
Due to the fact that the for loop will keep repeating until nil is returned, you can cause yourself to crash if you don't use it cautiously
Ex:
local function myPairs()
return function()
return 1,2
end
end
for i, v in myPairs() do
print(i,v)
end
for v in function() return 1 end do end -- free roblox admin
Since it never returns nil and never stops, it's basically the same as
while true do end
Now that you have mastered the ways of iterator functions, you are now considered an epic roblox scripter Source: trust me
Note2: Yes yes I know iterators other than pairs and ipairs exist, and I may update this thread in the future to include coroutine iteration, ex:
for i in coroutine.wrap(function() coroutine.yield(1) end) do
print(i)
end
Thank you for reading, I hope you found this somewhat useful!