An if in Zig is a structure that allows choosing between execution paths and also returning values. In any language, the ability to make decisions is fundamental: “if this happens, do that.”
In Zig, if is not just a control flow statement; it is also an expression.
This means that an if block can evaluate and return a value, allowing us to write much more concise code and eliminate syntactic redundancies from the past.
The basic if statement
Let’s start with the familiar. The basic structure of a conditional in Zig is almost identical to C, but with a key difference: parentheses around the condition are mandatory and the condition must be strictly a boolean.
const active: bool = true;
if (active) {
std.debug.print("The system is active\n", .{});
} else {
std.debug.print("System shutdown\n", .{});
}Reminder: only booleans
As we saw in the primitive types chapter, Zig has no concept of “truthy” or “falsy”.
if (1)-> Compilation error.if (ptr)-> Compilation error.if (name.len)-> Compilation error.
We must be explicit: if (quantity > 0), if (ptr != null).
The if as an expression
In languages like C++ or JavaScript, if we want to assign a value to a variable based on a condition, we usually use the ternary operator (condition ? a : b).
In Zig, the ternary operator does not exist. We don’t need it, because if itself can do that job more readably.
We can assign the result of an if directly to a variable:
const age: u8 = 18;
// The if returns a value, which is stored in 'ticket_type'
const ticket_type = if (age >= 18) "Adult" else "Minor";
std.debug.print("Ticket type: {s}\n", .{ticket_type});For this to work, two rules must be met:
- All branches must return a value. You cannot have an
ifthat returns something and anelsethat does nothing. - The types must be compatible. You cannot return a
u8in theifand aboolin theelse.
A single syntax
By eliminating the ternary operator, Zig reduces the surface area of the language. There is no one form for statements and another for expressions: only the if syntax exists, which adapts to the context.
This encourages immutability (const). In other languages, we sometimes declare var x; and then use an if to fill it. In Zig, we can declare const x = if (...) directly.
Complex expressions in blocks
What if the logic for calculating the value is complex and requires multiple lines? Zig allows using code blocks as expressions.
In these cases we do not use return, because that would terminate the entire function. The block must have a label and return its result via break :label value.
const score: u32 = 85;
const grade = if (score > 90) "A" else if (score > 80) grade_label: {
// We can do calculations here
std.debug.print("Almost perfect...\n", .{});
// Return the value of the labeled block
break :grade_label "B";
} else "C";Zig does not implicitly return the last expression of a block. If a branch uses braces and must produce a value, it must be returned with a labeled break.
if with optionals and errors
Although we will dedicate entire chapters to memory management and error handling, it is impossible to talk about if in Zig without mentioning its use for unwrapping values.
In Zig, you will often have variables that can be a value or null (Optionals). The if in Zig has a special syntax to safely capture that value:
const possible_number: ?i32 = 42; // The '?' indicates it can be null
// "If possible_number has a value, capture it in 'n' and enter"
if (possible_number) |n| {
std.debug.print("The number is: {d}\n", .{n});
} else {
std.debug.print("It's null\n", .{});
}This structure (if (variable) |capture|) is ubiquitous in Zig and is how we avoid the infamous “Null Pointer Exception” errors.
Variable scope
Finally, remember that Zig uses lexical block scoping ({}). If you declare a variable inside the braces of an if, that variable only exists within those braces.
if (condition) {
const secret = 123;
}
// Error: use of undeclared identifier 'secret'
// secret does not exist here outsideThis limits the visibility of temporary names and prevents them from being used outside the place where they make sense.