-- Code in italics is wrong
function run()
-- do something
run()
end
run()
and wondering why they get a stack overflow. This is not a good way to make something run more than once. Nor is os.reboot)
Sometimes you want to make a section of code run more than once. Lua provides several constructs, known as loops.
Note:
In this tutorial, text in <angle brackets=""> indicates where you should write something, eg: print(<thing to="" print="">)
Note:
Within a function, code runs from top to bottom unless otherwise specified.
Most of you should know this by now, but it's not obvious to everyone and I have seen code written by people who didn't know it.
In particular, this means code after the loop will not run until the loop has finished.
Note:
A condition can be any value - you could write something like "while 7 do". For the purposes of loops and if statements, Lua considers nil to be equivalent to false, and any other value to be equivalent to true.
While loops
A while loop runs a block of code over and over until some condition is false.
This is the most fundamental type of loop in Lua, and can be used to simulate all other loops.
First it checks the condition, then if the condition is true it runs the code, then it checks the condition, runs the code if it's true, etc… When it checks the condition, and it's false, it goes on to the code after the loop.
The syntax for a while loop in Lua is:
while <condition> do
<code>
end
and does this:1. Check the condition.
2. If the condition is true:
2A. Run the code.
2B. Go to step 1.
Note: Each time the computer "goes around the loop" is called an iteration.
Example:
print("Do you want me to spam you?")
while read() == "yes" do
print("spam")
print("spam")
print("spam")
print("spam")
print("spam")
print("Do you want me to do it again?")
end
print("OK, bye then")
This will do the following:
1. Print "Do you want me to spam you?"
2. Wait for the user to enter some text.
3. If that text is "yes" then:
3A. Print "spam" five times
3B. Print "Do you want me to do it again?"
3C. Go to step 2.
4. Print "OK, bye then"
Notice that the condition is only checked at the start of each iteration.
If we have something like this:
A = 7
while A == 7 do
A = 8
print("Hi!")
end
then it will print "Hi!" once, even though A has stopped being 7 when the computer gets to the print("Hi!")Repeat/until loops
Repeat/until loops are a variation on while loops, where the condition is not checked until the end of each iteration, and the loop runs as long as the condition is false (instead of true).
The computer runs the code, then checks the condition, then runs the code, then checks the condition, etc… until the condition is true when the computer checks it.
"Do/while loops" are a similar variation found in some other languages. Lua does not have do/while loops so they will not be covered here.
The syntax in Lua is:
repeat
<code>
until <condition>
which does this:1. Run the code.
2. Check the condition.
3. If the condition is false, go to step 1.
Example:
repeat
print("spam")
print("spam")
print("spam")
print("spam")
print("spam")
print("Do you want me to keep spamming you?")
until read() == "no"
print("OK, bye then")
This is similar to the last example, but not quite the same. For one thing, it will only stop when the user enters "no", instead of anything except "yes". For another, it will always spam at least once.
It does exactly this:
1. Print "spam" five times.
2. Print "Do you want me to keep spamming you?"
3. Wait for the user to enter a line of text.
4. If they didn't enter "no", go to step 1.
5. Print "OK, bye then"
Numeric for loops
A numeric for loop increments a variable on each iteration. You can use a while or repeat/until loop for this purpose, but it's used so commonly that it has its own type of loop.
In other languages, these are often just called "for loops".
In Lua, the syntax is either of these:
for <variable> = <start>, <stop> do
<code>
end
for <variable> = <start>, <stop>, <step> do
<code>
end
This is easier to explain by example, so here is a very simple use of a numeric for loop:
for number = 1, 5 do
print("Hello world! ", number)
end
This will print:
Hello world! 1
Hello world! 2
Hello world! 3
Hello world! 4
Hello world! 5
As you can see, this ran five iterations.
On the first iteration, number was equal to 1.
On the second iteration, number was equal to 2, and so on.
<variable> (in this case, number) is just the name for the variable that changes automatically. You can use any valid variable name. Traditionally, if there's no obvious name for this variable it will be called i, j or k. This variable is also known as the loop counter.
<start> (in this case, 1) is the value the variable has on the first iteration.
<stop> (in this case, 5) is the value the variable has on the last iteration.
We haven't covered <step> yet. <step> indicates how much the variable should change by on each iteration, and if you don't specify it, it will be 1, as in the example above. Let's change the previous example by adding 2 as <step>:
for number = 1, 5, 2 do
print("Hello world! ", number)
end
This will print:
Hello world! 1
Hello world! 3
Hello world! 5
As you can see, the loop counter still starts at 1 and ends at 5, but it increases by 2 on each iteration.You can also use a negative <step>:
for number = 5, 1, -1 do
print(number)
end
print("Blast-off!")
prints:
5
4
3
2
1
Blast-off!
Numeric for loops are also useful for repeating code a certain number of times:
for k = 1, 5 do
print("spam")
end
prints:
spam
spam
spam
spam
spam
Generic for loop
This is the most powerful loop in Lua. Its main use is with tables, so if you haven't learned about tables yet, skip this section and come back later.
The syntax is:
for <variable list=""> in <iterator expression=""> do
<code>
end
<iterator expression=""> sounds scary, and it is, if you look at the details. But you don't need to know that, all you need to know is what things you can put there.
<variable list=""> is a comma-separated list of variables to use in the loop, and it depends on <iterator expression="">.
The most common use is with the built-in pairs or ipairs function and tables:
for <key variable="">, <value variable=""> in pairs() do
<code>
end
Example:
t = {
"hello world!",
one = 1,
five = 5,
seven = 7,
}
for key, value in pairs(t) do
print(key," is ",value)
end
prints: (order of lines may vary)
1 is "hello world!"
five is 5
seven is 7
one is 1
It picks an entry from the table, sets the key and value variables to the key and value, and then runs the code. Then it picks a different entry, etc, until it's processed all the entries. There is no guarantee about which order it will choose the entries in.
Note: Do not add new entries to the table inside the loop, or you'll get undefined behaviour (which means literally anything can happen; it might work, it might not, it might raise an error). You are allowed to delete entries or modify existing ones.
ipairs is similar, but it only chooses numeric keys starting from 1 and until the first gap, and it is guaranteed to return the entries in the right order.
t = {
"line 1",
"line 2",
"line 3",
[6] = "line 6",
[4] = "line 4",
five = "line 5"
}
for key, value in ipairs(t) do
print(key," is ",value)
end
prints:
line 1
line 2
line 3
line 4
Notice that the lines were printed in the order they appeared in the table. "line 5" was not printed as it was not associated with a numeric key, and "line 6" was not printed as it appears after the first gap. (since there was no table entry with 5 as the key)For advanced coders:
A useful effect of the generic for loop is that it can be used to call a function repeatedly until it returns nil. This code will print all the lines in the file "hello":
f = fs.open("hello", "r")
for line in f.readLine do -- note: no () after readLine
print(line)
end
f.close()
</code></value></key></iterator></variable></iterator></code></iterator></variable></step></step></step></step></stop></start></variable></code></step></stop></start></variable></code></stop></start></variable></condition></code></code></condition></thing></angle>