switch (Pattern Matching)
In Zig, switch lets you branch on enums, integers, optional types, and other values using pattern matching. The syntax is similar to C's switch, but all patterns must be exhaustive — omitting a case results in a compile error, preventing missed conditions. switch can also be used as an expression that returns a value.
Syntax
// -----------------------------------------------
// switch statement — basic syntax
// -----------------------------------------------
switch (target_value) {
pattern1 => {
// executed when pattern1 matches
},
pattern2, pattern3 => {
// multiple patterns can be grouped together
},
pattern4...pattern5 => {
// range pattern (integers only). matches pattern4 through pattern5, inclusive
},
else => {
// executed when no pattern matches
},
}
// -----------------------------------------------
// switch expression — returning a value
// -----------------------------------------------
const variable = switch (target_value) {
pattern1 => valueA,
pattern2 => valueB,
else => default_value,
};
// -----------------------------------------------
// switch on an enum (no else needed — must be exhaustive)
// -----------------------------------------------
const MyEnum = enum { A, B, C };
switch (enum_value) {
.A => { /* when A */ },
.B => { /* when B */ },
.C => { /* when C */ },
// if all enum variants are listed, else can be omitted
}
// -----------------------------------------------
// switch on an optional type
// -----------------------------------------------
switch (optional_value) {
null => { /* when null */ },
else => |v| { /* when a value exists. use |v| to access the unwrapped value */ },
}
Syntax Reference
| Syntax / Method | Description |
|---|---|
switch (x) { ... } | Branches on value x using pattern matching. A compile error occurs if all patterns are not covered. |
pattern => expr | Evaluates the expression when the pattern matches. Use a { } block for multi-line logic. |
A, B => expr | Groups multiple patterns into a single arm, separated by commas. |
A...B => expr | Integer range pattern. Matches all values from A to B, inclusive. |
else => expr | Fallback arm executed when no other pattern matches. |
else => |v| | Uses capture syntax in the fallback arm to receive the matched value as v. |
const x = switch (...) { ... }; | Uses switch as an expression and assigns the result to a variable. |
.EnumVariant | Enum patterns are specified with dot notation. The type name can be omitted due to type inference. |
null => expr | Pattern for when an optional type is null. |
inline else | Inlines all arms at compile time. Used when a comptime value is required. |
Sample Code
jujutsu_switch.zig
// jujutsu_switch.zig — sample demonstrating switch pattern matching in Zig
// uses Jujutsu Kaisen characters to explore
// switch on enums, integers, and optional types
const std = @import("std");
// -----------------------------------------------
// enum definition — sorcerer grade
// -----------------------------------------------
// represents a jujutsu sorcerer's grade as an enum
const Grade = enum {
Special, // special grade
First, // grade 1
SemiFirst, // semi-grade 1
Second, // grade 2
Third, // grade 3
};
// -----------------------------------------------
// enum definition — cursed technique type
// -----------------------------------------------
const Technique = enum {
LimitlessCursedTechnique, // Limitless (Gojo Satoru)
BlackFlash, // Black Flash (Itadori Yuji)
TenShadows, // Ten Shadows Technique (Fushiguro Megumi)
NailsBlood, // Straw Doll Technique (Kugisaki Nobara)
RatioTechnique, // Ratio Technique (Nanami Kento)
};
// struct representing character data
const Sorcerer = struct {
name: []const u8,
grade: Grade,
technique: Technique,
cursed_energy: ?u32, // cursed energy level (null if unmeasurable)
};
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// -----------------------------------------------
// switch on an enum
// -----------------------------------------------
// define Jujutsu Kaisen characters
const sorcerers = [_]Sorcerer{
.{ .name = "五条悟", .grade = .Special, .technique = .LimitlessCursedTechnique, .cursed_energy = null },
.{ .name = "虎杖悠仁", .grade = .First, .technique = .BlackFlash, .cursed_energy = 8700 },
.{ .name = "伏黒恵", .grade = .SemiFirst, .technique = .TenShadows, .cursed_energy = 6200 },
.{ .name = "釘崎野薔薇",.grade = .Second, .technique = .NailsBlood, .cursed_energy = 4800 },
.{ .name = "七海建人", .grade = .First, .technique = .RatioTechnique, .cursed_energy = 7100 },
};
try stdout.print("=== Sorcerer Grade Check ===\n\n", .{});
for (sorcerers) |s| {
// pattern match on the enum with switch
// since all enum variants are listed, else is not needed
const grade_label = switch (s.grade) {
.Special => "Special Grade",
.First => "Grade 1",
.SemiFirst => "Semi-Grade 1",
.Second => "Grade 2",
.Third => "Grade 3",
};
// convert technique to a label with switch
const technique_label = switch (s.technique) {
.LimitlessCursedTechnique => "Limitless",
.BlackFlash => "Black Flash",
.TenShadows => "Ten Shadows",
.NailsBlood => "Straw Doll",
.RatioTechnique => "Ratio Technique",
};
try stdout.print("[{s}] {s} / {s}\n", .{ s.name, grade_label, technique_label });
}
// -----------------------------------------------
// switch on integers (range patterns and multiple patterns)
// -----------------------------------------------
try stdout.print("\n=== Cursed Energy Rank ===\n\n", .{});
// determine power rank from cursed energy level
// integer switch supports range patterns (...) and multiple patterns (,)
const power_levels = [_]u32{ 9999, 8700, 6200, 4800, 7100 };
const names = [_][]const u8{ "五条悟", "虎杖悠仁", "伏黒恵", "釘崎野薔薇", "七海建人" };
for (names, power_levels) |name, power| {
const rank = switch (power) {
9000...9999 => "Top Tier",
7000...8999 => "High Tier",
5000...6999 => "Mid Tier",
1, 2 => "Weakest (excluding unmeasurable)", // example of multiple patterns
0 => "No cursed energy",
else => "Standard",
};
try stdout.print("{s} (cursed energy: {d}) -> {s}\n", .{ name, power, rank });
}
// -----------------------------------------------
// switch on an optional type
// -----------------------------------------------
try stdout.print("\n=== Cursed Energy Detail (optional switch) ===\n\n", .{});
for (sorcerers) |s| {
// use switch on a ?u32 optional
// the null arm and else => |v| arm handle presence and absence of a value
const energy_str: []const u8 = switch (s.cursed_energy) {
null => "unmeasurable",
else => |v| blk: {
// labeled block to build a string result
// compares the cursed energy value and returns a label
_ = v; // explicitly mark v as used (suppresses unused variable warning)
break :blk if (s.cursed_energy.? >= 8000) "high" else "standard";
},
};
try stdout.print("{s}: cursed energy -> {s}\n", .{ s.name, energy_str });
}
// -----------------------------------------------
// switch statement (without returning a value)
// -----------------------------------------------
try stdout.print("\n=== Technique Type Message ===\n\n", .{});
// use switch as a statement, not an expression (return value is discarded)
const gojo = sorcerers[0];
switch (gojo.technique) {
.LimitlessCursedTechnique => {
try stdout.print("{s}'s technique: Limitless\n", .{gojo.name});
try stdout.print(" - Details: Blue (attraction), Red (repulsion), Purple (hollow)\n", .{});
try stdout.print(" - Combined with the Six Eyes, considered the strongest technique\n", .{});
},
.BlackFlash, .TenShadows, .NailsBlood, .RatioTechnique => {
// handle multiple patterns together
try stdout.print("{s} is a character other than Gojo Satoru\n", .{gojo.name});
},
}
}
zig run jujutsu_switch.zig === Sorcerer Grade Check === [五条悟] Special Grade / Limitless [虎杖悠仁] Grade 1 / Black Flash [伏黒恵] Semi-Grade 1 / Ten Shadows [釘崎野薔薇] Grade 2 / Straw Doll [七海建人] Grade 1 / Ratio Technique === Cursed Energy Rank === 五条悟 (cursed energy: 9999) -> Top Tier 虎杖悠仁 (cursed energy: 8700) -> High Tier 伏黒恵 (cursed energy: 6200) -> Mid Tier 釘崎野薔薇 (cursed energy: 4800) -> Standard 七海建人 (cursed energy: 7100) -> High Tier === Cursed Energy Detail (optional switch) === 五条悟: cursed energy -> unmeasurable 虎杖悠仁: cursed energy -> high 伏黒恵: cursed energy -> standard 釘崎野薔薇: cursed energy -> standard 七海建人: cursed energy -> standard === Technique Type Message === 五条悟's technique: Limitless - Details: Blue (attraction), Red (repulsion), Purple (hollow) - Combined with the Six Eyes, considered the strongest technique
Overview
Zig's switch is a powerful control flow construct that branches on a value using pattern matching. Its defining feature is exhaustiveness checking — when switching on an enum or integer, every possible pattern must be covered or a compile error is raised. This means that when a new enum variant is added, any missing handling is caught at compile time. When exhaustive coverage is not possible, add an else arm as a fallback.
For integer switch, range patterns using A...B and multiple patterns separated by commas are supported. For optional types (?T), write an explicit null arm and use else => |v| to unwrap the value when it exists. Because switch also works as an expression, you can use it directly in an assignment like const x = switch (...) { ... };. For general conditional branching, see if / else. For details on optional types, see Optional Types.
If you find any errors or copyright issues, please contact us.