⚡ Zig Guide LiveUnofficial
✓ Zig 0.17.0-dev.1454+5faa79730On an older Zig?

If Expressions

const std = @import("std");
const expect = std.testing.expect;

test "if as a statement" {
    const a = true;
    var x: u16 = 0;
    if (a) {
        x += 1;
    } else {
        x += 2;
    }
    try expect(x == 1);
}

test "if as an expression" {
    const a = true;
    // The ternary equivalent; both branches must yield the same type.
    const x: u16 = if (a) 1 else 2;
    try expect(x == 1);
}

test "if unwraps an optional" {
    const maybe: ?u8 = 42;
    const doubled: u16 = if (maybe) |value| value * 2 else 0;
    try expect(doubled == 84);
}

There is no truthiness in Zig. if (1) does not compile; neither does if (pointer). The condition must be a bool, which removes an entire family of bugs where a value is accidentally treated as a flag.

if produces a value

Zig has no ternary operator because it does not need one:

const x: u16 = if (a) 1 else 2;

Both branches must agree on a type. Used as an expression, the else is mandatory: there would otherwise be no value when the condition is false.

Unwrapping

if is also how you get inside an optional, using payload capture:

if (maybe) |value| { ... } else { ... }

The same shape works for error unions with else |err|. This is a recurring theme: the check and the unwrap are one construct, so they cannot fall out of sync.