Statements & Control Flow
Blocks
A block is a sequence of statements. Execution is sequential.
do
-- this is a block
local x = 10
print(x)
end
Assignment
-- Single
x = 10
t.key = "value"
-- Multiple (all RHS evaluated first, then assigned)
a, b = 1, 2
a, b = b, a -- swap
-- Extra/missing values
a, b = 1, 2, 3 -- 3 discarded
a, b = 1 -- b = nil
[!warning] Global assignment side effects
x = 10triggers__newindexon_ENVif its metatable has one.
Control structures
if / elseif / else
if condition then
-- ...
elseif other_condition then
-- ...
else
-- ...
end
- Conditions: only
nilandfalseare falsy - No parentheses required (but allowed)
while
while condition do
-- body
end
repeat...until
repeat
-- body
until condition
- Condition is evaluated after body (body runs at least once)
- Variables declared inside are visible in the condition
repeat
local line = io.read()
until line ~= "" -- 'line' is visible here
Numeric for
for var = start, stop, step do
-- body
end
stepdefaults to1- Control variable is local to the loop
- Values are evaluated once at start
- Loop runs while
var <= stop(step > 0) orvar >= stop(step < 0)
for i = 1, 10 do print(i) end -- 1 to 10
for i = 10, 1, -1 do print(i) end -- 10 to 1
for i = 0, 1, 0.1 do print(i) end -- floats work too
[!tip] Don't modify the control variable It's local and re-assigned each iteration. Changes are overwritten.
Generic for
for var_list in explist do
-- body
end
The iterator function is called each iteration. Three forms you'll see most:
-- pairs: all key-value pairs (unordered)
for k, v in pairs(t) do print(k, v) end
-- ipairs: sequential integer keys (1, 2, 3, ...)
for i, v in ipairs(t) do print(i, v) end
-- io.lines: lines of a file
for line in io.lines("file.txt") do print(line) end
Under the hood, the generic for calls f(state, var) repeatedly until it returns nil:
-- Equivalent to: for var_1, ..., var_n in explist do body end
local f, s, var = explist
while true do
local var_1, ..., var_n = f(s, var)
if var_1 == nil then break end
var = var_1
body
end
break
Exits the innermost loop (while, repeat, for).
for i = 1, 100 do
if i > 10 then break end
print(i)
end
goto
Jumps to a label in the same function/block scope.
for i = 1, 10 do
if i == 5 then goto skip end
print(i)
::skip::
end
- Labels are written
::name:: - Forward and backward jumps allowed
- Cannot jump into a block (only out of one)
- Useful for breaking out of nested loops
::retry::
local ok, err = try_something()
if not ok then goto retry end
return
Must be the last statement in a block. To return in the middle, use do...end:
function f()
if condition then
do return early_value end
end
return final_value
end
Can return multiple values:
function swap(a, b)
return b, a
end
No return → function returns nothing (no values).
Labels and goto rules
-- Valid: jumping out of loop
for i = 1, 10 do
if done then goto exit end
end
::exit::
-- INVALID: jumping into a block
goto inside
do
::inside:: -- error: label is visible but jump enters scope
end
Statement summary
| Statement | Syntax |
|---|---|
| Assignment | var = expr |
| Local | local var = expr |
| Block | do ... end |
| If | if cond then ... elseif ... else ... end |
| While | while cond do ... end |
| Repeat | repeat ... until cond |
| Numeric for | for i = start, stop, step do ... end |
| Generic for | for vars in iter do ... end |
| Break | break |
| Goto | goto label / ::label:: |
| Return | return exprs |
| Function call | func(args) |