This post will walk you through what Lua expressions are, the types of expressions, operator precedence, and best practices.
What Is an Expression in Lua?
In Lua, an expression is a piece of code that evaluates to a value. You can use expressions to assign values, control flow, or compute data.
Examples of Lua expressions:
2 + 3 --> 5
"a" .. "b" --> "ab"
true and false --> false
x * y + 1 --> evaluates based on x and y
Anything that results in a value—whether a number, string, boolean, table, or function—is considered an expression.
Types of Lua Expressions
Lua supports a rich set of expression types:
1. Literals
Basic values like:
42 -- number
"hello" -- string
true, false -- boolean
nil -- absence of value
2. Variables
Refers to named storage locations:
local x = 5 -- x is a variable; '5' is a literal expression
3. Arithmetic Expressions
+ - * / % ^ -- standard arithmetic operations
Example:
(2 + 3) * 4 --> 20
4. Relational Expressions
Return a boolean result:
== ~= < > <= >=
5 < 10 --> true
"a" == "a" --> true
5. Logical Expressions
Used for conditional evaluation:
and or not
true and false --> false
not true --> false
Lua uses short-circuit evaluation:
a and bevaluatesbonly ifais truthy.a or bevaluatesbonly ifais falsy.
x = nil or 5 --> x = 5
6. Concatenation
Use .. to concatenate strings:
"foo" .. "bar" --> "foobar"
7. Table Constructors
Used to create tables (Lua’s only data structure):
{} -- empty table
{1, 2, 3} -- array-like table
{name = "Lua", ver = 5.4} -- dictionary-like table
8. Function Calls
You can call:
- Global functions (
print("hello")) - Table fields (
table.insert(t, val)) - Anonymous functions (
(function() return 5 end)())
function add(a, b) return a + b end
x = add(2, 3) --> 5
9. Anonymous Functions (Lambdas)
Lua supports inline function expressions:
square = function(x) return x * x end
print(square(4)) --> 16
10. Parenthesized Expressions
Used for grouping:
(2 + 3) * 4 --> 20
Also useful for forcing single values from multi-return functions:
function multi() return 1, 2 end
x = (multi()) --> x = 1; only first value is returned
Operator Precedence in Lua
Understanding precedence is crucial to avoid bugs.
| Precedence | Operators | Description |
|---|---|---|
| 1 (highest) | ^ |
Exponentiation |
| 2 | not - (unary) # |
Logical not, unary minus, length |
| 3 | * / % |
Multiplication, division, modulo |
| 4 | + - |
Addition, subtraction |
| 5 | .. |
String concatenation |
| 6 | < > <= >= == ~= |
Comparisons |
| 7 (lowest) | and |
Logical AND |
| 8 | or |
Logical OR |
Note: .. (concatenation) is right-associative, as is ^ (exponentiation).
2 ^ 3 ^ 2 --> 2 ^ (3 ^ 2) = 512
"a" .. "b" .. "c" --> "abc"
Use parentheses to ensure clarity:
(2 + 3) * 4 ~= 2 + (3 * 4)
Expression Evaluation Rules
- Truthiness: Only
falseandnilare falsy. Everything else (including0and empty strings) is truthy. - Multiple Returns: A function returning multiple values behaves differently depending on context.
function f() return 1, 2 end
x = f() --> x = 1
x, y = f() --> x = 1, y = 2
print(f()) --> prints 1 2
print((f())) --> prints 1
Common Pitfalls
-
Confusing
==and=:=is assignment.==checks equality.
-
Misunderstanding operator precedence:
print(2 + 3 * 4) --> 14, not 20
- Using
..on non-strings without conversion:
print("The value is: " .. 123) --> Works
print("Value: " .. nil) --> Error!
Convert explicitly:
print("Value: " .. tostring(nil)) --> "Value: nil"
- Wrong assumptions about truthiness:
if 0 then print("yes") end --> prints "yes"
Best Practices
- Always use parentheses when unsure about precedence.
- Prefer
localvariables for clarity and performance. - Avoid using
nilin expressions unless intended. - Use
tostring()when concatenating mixed types.