Learn Lua in Neovim: Logical Operators — and, or, not & Ternary Idiom | Episode 8
Video: Learn Lua in Neovim: Logical Operators — and, or, not & Ternary Idiom | Episode 8 by Taught by Celeste AI - AI Coding Coach
Lua Logical Operators: and, or, not, and the Ternary Idiom
andandorshort-circuit. They return operands, not booleans.x and a or bis Lua's ternary — but watch the gotcha whenaisfalseornil.
Lua's and/or operators are unusually powerful because they don't just return true/false — they return one of their operands. That property is what makes the x and a or b "ternary" idiom work.
The basics
local age = 12
local height = 140
-- AND: both conditions must be true
if age >= 10 and height >= 130 then
print("You can ride!")
else
print("Sorry, not allowed.")
end
Two conditions joined by and — both must be true for the whole expression to be true. With 12 >= 10 (true) and 140 >= 130 (true), the body runs.
local has_ticket = true
local is_vip = false
if has_ticket or is_vip then
print("Welcome to the park!")
else
print("You need a ticket.")
end
or is "either one is enough." has_ticket is true, so the body runs regardless of is_vip.
NOT
local park_closed = false
if not park_closed then
print("The park is open!")
end
not flips the truthiness. not false is true; not true is false; not nil is true (because nil is falsy).
not always returns a real boolean (true or false). and and or do not — that's the trick.
Short-circuit evaluation
print(1 and 2) -- 2
print(1 or 2) -- 1
print(false and 2) -- false
print(false or 2) -- 2
print(nil and 2) -- nil
print(nil or 2) -- 2
What's going on?
x and y — if x is falsy, returns x. Otherwise returns y.
x or y — if x is truthy, returns x. Otherwise returns y.
So:
1 and 2—1is truthy, so returns2.1 or 2—1is truthy, so returns1(doesn't even look at2).false and 2—falseis falsy, so returnsfalse.false or 2—falseis falsy, so returns2.
This short-circuits — if the first operand decides the answer, the second isn't evaluated. That's a feature: it lets you write things like x and x.field (won't crash if x is nil).
The "ternary" idiom
Lua doesn't have a cond ? a : b ternary like C. It uses and/or:
local score = 85
local grade = score >= 60 and "Pass" or "Fail"
print("Result: " .. grade)
Walk it through:
score >= 60istrue(truthy).true and "Pass"is"Pass"."Pass" or "Fail"is"Pass"(truthy first operand wins).
If score = 50:
score >= 60isfalse.false and "Pass"isfalse(skipped second arg).false or "Fail"is"Fail".
Result: "Fail". Same effect as (score >= 60) ? "Pass" : "Fail" in C.
The ternary gotcha
local enabled = true
local label = enabled and false or "default"
print(label) -- "default" (unexpected!)
The "true value" is false itself, which is falsy. So:
enabled and false—enabledtruthy, returnsfalse.false or "default"—falsefalsy, returns"default".
You wanted false, got "default". The and ... or idiom only works when the "true value" is itself truthy.
For correct behaviour with falsy "true values," use a real if:
local label
if enabled then
label = false
else
label = "default"
end
Verbose, but unambiguous.
Defaults with or
local function greet(name)
name = name or "stranger"
print("Hello, " .. name)
end
greet("Alice") -- "Hello, Alice"
greet() -- "Hello, stranger"
name or "stranger" returns name if it's truthy, otherwise "stranger". Standard Lua idiom for default arguments.
But beware: if name is the empty string "", it's truthy in Lua, so the default doesn't kick in:
greet("") -- "Hello, " (empty greeting)
If empty strings should also use the default, check explicitly:
if name == nil or name == "" then
name = "stranger"
end
Combining operators
local age = 18
local has_id = true
local is_friday = true
if (age >= 18 and has_id) or is_friday then
print("Allowed")
end
Parentheses for clarity. Without them, and binds tighter than or (like * vs + in math), but readers shouldn't have to remember that.
Precedence in Lua, lowest to highest:
orand<,>,<=,>=,~=,==..(string concat)+,-*,/,//,%not,#, unary-^
But again — parentheses for anything non-trivial.
Common stumbles
Expecting and/or to return booleans. They return operands. print(2 and 3) is 3, not true.
The ternary gotcha. x and a or b breaks when a is false or nil. Use a real if then.
Defaulting with or for empty strings. s or "default" doesn't fire when s = "" (empty string is truthy). Check s == nil or s == "".
Using && and ||. Those are C-style. Lua uses and, or, not — keywords, not symbols.
Precedence surprises. not x == y parses as (not x) == y, not not (x == y). Add parens.
What's next
Episode 9: numeric for loops. for i = 1, 10 do ... end, with optional step. A countdown program and a multiplication table.
Recap
and, or, not for boolean logic. and and or return operands, not booleans, and short-circuit. The Lua "ternary" is cond and a or b — but only safe when a is truthy. Defaults with name or "default" (watch the empty-string edge case). Precedence: or < and < comparisons; use parens for clarity.
Next episode: numeric for loops.