Booleans and logic
Lesson 3.4
Programs make decisions by asking yes/no questions. In Lua the answers are the booleans true and false.
Comparisons
A comparison gives a boolean:
| Operator | Means | Example | Result |
|---|---|---|---|
== |
equal | 5 == 5 |
true |
~= |
not equal | 5 ~= 3 |
true |
< |
less than | 3 < 5 |
true |
> |
greater than | 3 > 5 |
false |
<= |
less or equal | 5 <= 5 |
true |
>= |
greater or equal | 4 >= 5 |
false |
“Not equal” is ~= in Lua. Many other languages use !=, which is an error in Lua.
local health = 6
print(health < 10) --> true
print(health == 20) --> false
print(health ~= 20) --> true
Strings compare too. == checks that they are exactly the same, including upper and lower case. < sorts them alphabetically, by byte value, so all uppercase letters come before lowercase ones:
print("stone" == "Stone") --> false
print("apple" < "banana") --> true
print("Zebra" < "apple") --> true
Values of different types are never equal: 1 == "1" is false. Comparing them with < is an error.
Truthy and falsy
Lua has a simple rule: only false and nil count as false. Everything else counts as true, including 0 and the empty string "".
| Value | Counts as |
|---|---|
false, nil |
false |
true, 0, -1, "", "false", {} |
true |
This is different from some other languages, where 0 is false. In Lua, 0 is a normal number.
and, or, not
not flips a boolean:
print(not true) --> false
print(not nil) --> true
print(not 0) --> false
and is true when both sides are true. or is true when at least one side is:
local has_pickaxe = true
local is_night = false
print(has_pickaxe and is_night) --> false
print(has_pickaxe or is_night) --> true
print(not is_night) --> true
and and or return values
and and or don’t just give true or false. They give one of their two sides:
a or bgivesaifais truthy, otherwiseb.a and bgivesbifais truthy, otherwisea.
print(nil or "default") --> default
print("Alex" or "default") --> Alex
print(5 and 10) --> 10
print(nil and 10) --> nil
They also stop early. If the left side of or is already truthy, the right side never runs. This is called short-circuit evaluation.
Default values with or
This makes or the usual way to give a default:
local nickname = nil
local shown = nickname or "Player"
print(shown) --> Player
A one-line if with and/or
condition and x or y picks x when the condition is true, and y otherwise:
local health = 4
local status = health < 5 and "low" or "ok"
print(status) --> low
The and/or trap
This only works when x is truthy. cond and false or "fallback" always gives "fallback", and so does cond and nil or "fallback". When the value in the middle might be false or nil, use a normal if.
Order of operations
not binds tightest, then comparisons, then and, then or. So a or b and c means a or (b and c). Add brackets whenever you mix and and or. It costs nothing and saves the reader from guessing.
local is_admin, is_owner, is_banned = false, true, false
print((is_admin or is_owner) and not is_banned) --> true
nil versus false
Both count as false, but they mean different things. nil means “no value at all”, while false is a real value meaning “no”. A setting stored as false was turned off on purpose; a setting that is nil was never set. To tell them apart, compare directly:
local pvp = false
print(pvp == nil) --> false
print(pvp == false) --> true
Try it
A player can enter the Nether portal when they are not in creative mode or they have permission, and their health is above 5. Write the expression for health = 8, creative = true, allowed = false, and print the result. Then use or to print "Unknown" when the variable world_name is nil.
Show a solution
local health, creative, allowed = 8, true, false
local can_enter = (not creative or allowed) and health > 5
print(can_enter) --> false
local world_name = nil
print(world_name or "Unknown") --> Unknown
Recap: comparisons give booleans, ~= means “not equal”, only false and nil are falsy, and x or default fills in missing values.