Control Flow in Lua: if, for, while, and repeat
Control flow statements are the backbone of any programming language. They let your program make decisions, repeat actions, and handle different conditions. In this tutorial, you’ll learn every control flow mechanism Lua offers.
This is the third tutorial in our Lua fundamentals series. If you’re new to Lua, start with our earlier tutorials on installing Lua and working with variables.
The if Statement
The if statement is the most fundamental control structure. It executes a block of code only when a condition evaluates to true.
local temperature = 25
if temperature > 30 then
print("It's hot outside!")
end
The condition after if must evaluate to a boolean value. In Lua, only nil and false are falsy—everything else is truthy, including 0 and empty strings.
if-elseif-else Chains
For more complex decision-making, use elseif and else:
local score = 85
if score >= 90 then
print("Grade: A")
elseif score >= 80 then
print("Grade: B")
elseif score >= 70 then
print("Grade: C")
else
print("Grade: F")
end
You can chain as many elseif blocks as needed. Lua evaluates them top-to-bottom and stops at the first true condition.
Numeric for Loops
The numeric for loop runs a specific number of times:
-- Print numbers 1 to 5
for i = 1, 5 do
print(i)
end
-- With step value
for i = 10, 0, -2 do
print(i) -- Prints: 10, 8, 6, 4, 2, 0
end
The syntax is for var = start, end, [step] do. The step defaults to 1 if omitted.
Generic for Loops
Generic for works with iterators, commonly used to iterate over tables:
local fruits = {apple = 1, banana = 2, cherry = 3}
-- Iterate over key-value pairs
for key, value in pairs(fruits) do
print(key, value)
end
-- Iterate over array-like tables
local colors = {"red", "green", "blue"}
for index, color in ipairs(colors) do
print(index, color)
end
Use pairs() for arbitrary key-value iteration and ipairs() for sequential array-style iteration.
While Loops
A while loop repeats as long as its condition remains true:
local count = 1
while count <= 5 do
print(count)
count = count + 1
end
Be careful—unlike for loops, while loops can create infinite loops if the condition never becomes false.
repeat…until Loops
The repeat...until loop executes at least once, then checks its condition:
local input
repeat
print("Enter quit to exit")
input = io.read()
until input == "quit"
print("Goodbye!")
This is useful when you need to prompt for input before validating.
Breaking and Continuing
Use break to exit a loop immediately:
for i = 1, 10 do
if i == 5 then
break
end
print(i)
end
-- Prints: 1, 2, 3, 4
Lua doesn’t have a continue statement. Instead, nest your condition or use a flag variable.
Nested Control Flow
You can nest control structures inside each other:
local matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}
for i = 1, #matrix do
for j = 1, #matrix[i] do
if matrix[i][j] % 2 == 0 then
print("Even:", matrix[i][j])
end
end
end
Practical Example
Here’s a simple number guessing game combining everything:
local target = math.random(1, 10)
local attempts = 0
local guess
print("Guess a number between 1 and 10")
repeat
attempts = attempts + 1
io.write("Your guess: ")
guess = tonumber(io.read())
if guess < target then
print("Too low!")
elseif guess > target then
print("Too high!")
end
until guess == target
print("Correct! It took you " .. attempts .. " attempts.")
Understanding Truthiness
Lua’s truthiness is simple but powerful. Only nil and false are falsy—everything else is truthy, including zero, empty strings, and even empty tables. This affects how conditions evaluate:
local value = 0
if value then
print("Truthy!") -- This prints because 0 is truthy
end
if value ~= nil then
print("Not nil!") -- This also prints
end
This behavior differs from languages like Python or JavaScript. Understanding it prevents subtle bugs, especially when checking for missing values.
Common Pitfalls
Several mistakes trip up newcomers to Lua:
Forgetting the then keyword:
-- Wrong
if temperature > 30
print("Hot")
-- Correct
if temperature > 30 then
print("Hot")
end
Off-by-one errors in numeric for loops:
-- This prints 1 to 4, not 1 to 5
for i = 1, 5 - 1 do
print(i)
end
Infinite while loops:
-- Bug: count never changes
local count = 1
while count <= 5 do
print(count)
-- Missing: count = count + 1
end
Choosing the Right Loop
Different loops suit different situations:
- Use numeric for when you know the exact iteration count
- Use generic for when iterating over tables or custom iterators
- Use while when the loop condition depends on dynamic values
- Use repeat…until when you need the body to execute at least once
Choosing correctly makes your code clearer and less error-prone.
Summary
Lua provides straightforward control flow mechanisms:
if— Execute code conditionallyelseif— Additional conditionselse— Fallback code when all conditions are falsefor— Numeric and generic iterationwhile— Loop while condition is truerepeat...until— Loop until condition is true (always runs at least once)break— Exit a loop early
These building blocks let you create complex programs. Master them, and you’ll be writing Lua with confidence.