Make your own iterator function

Tired of pairs and ipairs? Well, make your own epic custom iterator function... I guess?

by JustAHolocene

Author Avatar

Iterators

Before we start, don't be like this guy

image|100x100

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

Making our own iterator function

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

]]--

Notes + end

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!

View in-game to comment, award, and more!