Skip to content
Lesson 8 of 18

Step 1 of 5 · Reading · ~3 min

Learn

Control Flow

Loops

Lua gives you three loop statements plus one iterator protocol. Which one you reach for depends on what you know before the loop starts.

Rendering diagram…

The numeric for

The header is for i = start, stop, step do, and both ends are inclusive. There is no < n in Lua: for i = 1, 5 really does visit 5.

for i = 1, 3 do
    print(i)
end
for i = 3, 1, -1 do
    print(i)
end

--> 1
--> 2
--> 3
--> 3
--> 2
--> 1

Three guarantees worth knowing, because beginners lean on them without realising:

  • The three numbers are evaluated once, before the first pass. Changing them inside the body does nothing to the loop.
  • i belongs to the loop. Assigning to it inside the body affects only that one pass, and after the loop i does not exist any more.
  • The default step is 1. Forgetting a negative step is the classic silent bug: for i = 10, 1 do counts upward from 10 to 1, an empty range, so the body never runs and nothing is printed at all.

✗ a float sneaking into the counter

for i = 1, 2, 0.5 do
    print(i)
end

--> 1.0
--> 1.5
--> 2.0

If any of the three numbers is a float, the counter is a float for the entire loop and every value prints with a .0 attached.

while and repeat

while tests before each pass. repeat tests after, so its body always runs at least once.

local n = 1
while n < 100 do
    n = n * 2
end
print(n)

--> 128
local i = 0
repeat
    i = i + 1
    local squared = i * i
until squared > 20
print(i)

--> 5

Look closely at that second one: squared is declared inside the body and still visible in the until condition. Lua deliberately extends the body's scope to cover the condition, which is what lets repeat ... until ok read the way you want it to.

break, and the missing continue

break leaves the innermost loop immediately. There is no continue in Lua at all.

✗ does not exist

for i = 1, 5 do
    if i % 2 == 0 then continue end
    print(i)
end

✓ invert the test and wrap the rest

for i = 1, 5 do
    if i % 2 ~= 0 then
        print(i)
    end
end

--> 1
--> 3
--> 5

Lua does have goto and a ::continue:: label as an escape hatch for deeply nested code, but restructuring with if is clearer and is what you will meet in most real Lua.

Looping over things that are not counters

The other for is the generic one, and it drives an iterator rather than a counter: for w in string.gmatch(line, "%S+") do. You have already used that shape to split a line into words. Tables bring their own iterators, ipairs and pairs, in the Tables chapter.

Your exercise

Hailstone Steps follows a number until it reaches 1. You do not know in advance how many rounds that takes, so the flowchart at the top of this page already tells you which loop to reach for.

The starter reads the start value and sets up a step counter. The mistakes the grader will catch: a numeric for needs a count you do not have; forgetting to count the final move gives a step total that is one short; and halving with / instead of // turns every later number into a float, so 3 becomes 3.0 and the output is wrong from the first even step onwards.

Up nextTables as ArraysTables — The One Data Structure

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…