Generic for

From Legacy Roblox Wiki
Revision as of 11:16, 4 August 2011 by >Merlin11188 (→‎Introduction: Edited the hyperlink)
Jump to navigationJump to search

Introduction

Basic for loops have already been covered in Loops. If you haven't already done so, please review Loops. Now, the generic for loop is a loop that traverses through the values returned by an iterator function. In layman's terms, an iterator function is a function that returns a function that returns some values. WHAAT? Let me show you an example:

Example
function callFunc(number) -- number is the number we start at
	-- This function is going to return a function
	return function()
		if number < 4 then -- If the number is less than 4
			number = number + 1 -- Add one to it
			return string.char(number + 95)
			 -- And return it's ascii representation plus 95. Note that there's only one value being returned.
		end
	end
end

for x in callFunc(1) do -- Since there's only one value being returned, you only need one variable!
	print(x)
end
for y in callFunc(3) do -- Same here.
	print(y)
end

Output:
a
b
c
c -- string.char(3 + 1 + 95) == string.char(99) == c


Discussion

The iterator is the number that keeps track of how many times a for loop is supposed to run. This is different from a the numeric for loop in Loops in that the numeric for loop there is simply an iterator:

Numeric for:

for i=20, 1, -2 do print(i) end

However, in the generic for loop we get the values returned by the iterator function. In the above function, callFunc, we saw that string.char(number + 95), not number itself, was returned. Here's an example using multiple return values:

Example
function times2(array)
	local i = 1 -- This is the iterator value
	return function()
		if array[i] ~= nil then -- Make sure it's there!
			i = i + 1 -- Add one to i, so this doesn't result in an infinite loop
			return i - 1, array[i - 1]*2 -- return the index (i -1) and the value*2 (array[i - 1]*2)
			else
		end
	end
end

y = {3, 4, 5}
for index, valTimes2 in times2(y) do -- Two, count 'em, two variables. That's because 2 values are returned!
	print(index, valTimes2) -- Print the index and the value times 2 to output.
end

Output:
1	6
2	8
3	10


That pretty much covers generic for loops! Read on for some final examples!

Examples

Example
months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}

revmonths = {}
    
for i, v in ipairs(months) do
	revmonths[v] = i -- Make the month name the index and the location the value
	print(v, revmonths[v])
end

Output:
January		1 -- revmonths.January = 1
February	2 -- revmonths.February = 2
March		3
April		4
May		5 -- Cinco de mayo!
June		6
July		7
August		8
September	9
October		10
November	11
December	12


Here's another example returning multiple values:

Example
string = {}
string.gfind = function(stringToSearch, Pattern, Start)
	local start = Start or 1 -- Default value is 1
	return function()
		local beginning, ending = stringToSearch:find(Pattern, start) -- Start searching at the specified location
		if beginning and ending then -- Check to make sure that the match is there
			start = ending + 1 -- Add one to the ending so the pattern will start to look after the last match
			return beginning, ending, stringToSearch:sub(beginning, ending) -- return the 3 values
		end
	end
end

local stringToSearch = "Hello! My name is merlin1188!"

for start, finish, value in string.gfind(stringToSearch, "%a+") do
	print("The match starts at " .. start ..", finishes at " .. finish .. ", and is " .. value)
end

Output:
The match starts at 1, finishes at 5, and is Hello
The match starts at 8, finishes at 9, and is My
The match starts at 11, finishes at 14, and is name
The match starts at 16, finishes at 17, and is is
The match starts at 19, finishes at 24, and is merlin


pairs and ipairs

pairs and ipairs are iterator functions that return table indices and their corresponding values. pairs iterates through the entire table, even if the index is non-numerical (such as "Hi"). ipairs iterates through the table at numerical index, starting at 1 until it reaches nil. Also, please note that pairs does not iterate through the table in any particular order. Here's an example of the difference:

Example
sampleTable = {[1] = "A", [2] = 2, [3] = "B", [5] = 5, Hi = "C"}
for i, v in ipairs(sampleTable) do
	print(i, v)
end
print("That was with ipairs. This is with pairs.")
for i, v in pairs(sampleTable) do
	print(i, v)
end

Output:
1	A -- 1
2	2 -- 2
3	B -- 3
That was with ipairs. This is with pairs.
2	2 -- 2
3	B -- 3
1	A -- 1
5	5 -- 5
Hi	C -- Hi