Learn Lua in Neovim: If Statements — if, elseif, else & Grade Calculator | Episode 7
Video: Learn Lua in Neovim: If Statements — if, elseif, else & Grade Calculator | Episode 7 by Taught by Celeste AI - AI Coding Coach
Lua If Statements: if, elseif, else, and a Grade Calculator
if condition then ... endfor branching.elseif(one word, no space) for chained alternatives.elsefor the fallback. Build a grade calculator from a numeric score.
Conditionals are how programs make decisions. Today's example is a grade calculator — a numeric score in, a letter grade out — that walks every form of Lua's if statement.
The grade calculator
local score = 92
if score >= 90 then
print("Grade: A")
elseif score >= 80 then
print("Grade: B")
elseif score >= 70 then
print("Grade: C")
elseif score >= 60 then
print("Grade: D")
else
print("Grade: F")
end
print("Your score: " .. score)
Five branches, one if, three elseifs, one else. Score 92 matches >= 90, so it prints "Grade: A" and skips the rest.
The basic shape
if condition then
-- code that runs when condition is true
end
Three keywords frame every if:
if— start the conditional.then— required after the condition; ends the test.end— closes the block. (No braces. No indentation-based blocks.)
Forget then or end and you get a parse error.
Adding else
local age = 18
if age >= 18 then
print("You can vote")
else
print("Too young")
end
else is the fallback. Whatever doesn't match the if falls into the else branch.
Chaining with elseif
if score >= 90 then
print("Grade: A")
elseif score >= 80 then
print("Grade: B")
elseif score >= 70 then
print("Grade: C")
end
elseif (one word, no space) is "else if" combined. Without it you'd write:
if score >= 90 then
print("A")
else
if score >= 80 then -- nested if = ugly
print("B")
else
-- ...
end
end
Each level of nesting needs its own end. elseif flattens that — one end for the whole chain.
Order matters
The branches are evaluated top-to-bottom. The first matching condition wins; the rest are skipped. So:
if score >= 60 then
print("D")
elseif score >= 90 then
print("A") -- never runs! the 60 branch matched first
end
For range checks, order from most-specific to least-specific (high to low for grades).
else is optional
if score < 0 then
print("Invalid score")
end
-- continues to next line whether or not the if matched
Plain if with no else is fine. It just means "do this block if true; do nothing if false."
Nested ifs
local age = 18
local has_id = true
if age >= 21 then
if has_id then
print("Welcome")
else
print("Need ID")
end
else
print("Too young")
end
Two levels of if. Each one needs its own end. Often and is cleaner:
if age >= 21 and has_id then
print("Welcome")
elseif age >= 21 then
print("Need ID")
else
print("Too young")
end
We cover and and or properly in episode 8 — they make conditional expressions a lot more compact.
What counts as truthy?
Recall from episode 5: only false and nil are falsy. Everything else is truthy.
if 0 then print("0 is truthy") end -- prints
if "" then print("'' is truthy") end -- prints
if "false" then print("'false' is truthy") end -- prints (it's a non-empty string!)
For "is this number positive," check if x > 0 then, not if x then.
A common pattern: validate first
print("Enter your score:")
local score = tonumber(io.read())
if score == nil then
print("That wasn't a number")
elseif score < 0 or score > 100 then
print("Score out of range")
elseif score >= 90 then
print("Grade: A")
elseif score >= 80 then
print("Grade: B")
-- ...
end
Validate before computing. The first two branches catch bad input; the rest do the actual grading. Reads top-to-bottom like a checklist.
Single-line ifs?
Lua doesn't have a special syntax for one-liners — every if needs then and end. You can compress:
if x > 0 then print("positive") end
Works fine. But there's no Python-style print("positive") if x > 0. Lua keeps the syntax uniform.
Common stumbles
Forgetting then. if x > 0 print("yes") end is a syntax error. then is mandatory.
Forgetting end. Especially in nested ifs, missing one end triggers a confusing error like "expected 'end' near 'else'." Indent consistently and the missing end becomes obvious.
else if instead of elseif. else if opens a new nested if that needs its own end. elseif doesn't. Two different things.
Range checks in wrong order. if x > 60 ... elseif x > 90 ... — the second branch never runs. Order high-to-low for descending ranges.
Treating non-boolean values as booleans without thought. if user_input then matches any non-nil value, including the string "false". Compare explicitly when in doubt: if user_input == "yes" then.
What's next
Episode 8: logical operators. and, or, not — and the surprising x and a or b "ternary" idiom that takes advantage of how and/or actually work.
Recap
if condition then ... end for conditionals. elseif (one word) chains alternatives. else for the fallback. Branches evaluate top-to-bottom; first match wins. Only false and nil are falsy. Always close with end.
Next episode: and, or, not.