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

Switch

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

test "switch as a statement" {
    var x: i8 = 10;
    switch (x) {
        -1...1 => x = -x, // inclusive ranges
        10, 100 => x = @divExact(x, 10), // multiple values
        else => {},
    }
    try expect(x == 1);
}

test "switch as an expression" {
    const x: i8 = 10;
    const y: i8 = switch (x) {
        -1...1 => -x,
        10, 100 => @divExact(x, 10),
        else => 0,
    };
    try expect(y == 1);
}

const Direction = enum { north, south, east, west };

fn isVertical(d: Direction) bool {
    // No `else` branch: the compiler proves every case is handled, so adding
    // a new enum tag later turns this into a compile error rather than a bug.
    return switch (d) {
        .north, .south => true,
        .east, .west => false,
    };
}

test "exhaustive switch over an enum" {
    try expect(isVertical(.north));
    try expect(!isVertical(.east));
}

Zig’s switch has no fallthrough, and it must be exhaustive: every possible value needs a branch, or the program does not compile.

Ranges and multiple values

switch (x) {
    -1...1 => ...,      // inclusive range
    10, 100 => ...,     // several values, one branch
    else => ...,
}

Note ... for ranges is inclusive on both ends, unlike the .. used in for ranges, which excludes the upper bound.

The exhaustiveness payoff

When switching over an enum and covering every tag, leave out else:

return switch (direction) {
    .north, .south => true,
    .east, .west => false,
};

Now adding a .up variant later turns this into a compile error pointing straight at the code that needs updating. Adding else => false would instead silently classify the new direction as horizontal. The else branch is a convenience that costs you the compiler’s help. Spend it deliberately.