# `switch` Expressions

### `switch` Expressions

A `switch` chooses one branch from several alternatives.

```zig
const name = switch (code) {
    200 => "ok",
    404 => "not found",
    500 => "server error",
    else => "unknown",
};
```

This is an expression. The value of the selected branch becomes the value of `name`.

The value being tested is called the switch operand.

```zig
switch (code) {
    ...
}
```

Each branch has one or more cases.

```zig
200 => "ok",
```

The value before `=>` is matched against the operand. The expression after `=>` is evaluated if the case matches.

Several cases can share one branch.

```zig
const kind = switch (ch) {
    'a', 'e', 'i', 'o', 'u' => "vowel",
    else => "other",
};
```

Ranges are allowed for integer and character values.

```zig
const class = switch (ch) {
    '0'...'9' => "digit",
    'a'...'z' => "lowercase",
    'A'...'Z' => "uppercase",
    else => "other",
};
```

The range includes both ends. The case `'0'...'9'` includes `'0'` and `'9'`.

A `switch` must be exhaustive. Every possible value must be handled.

For integers, this usually means using `else`.

```zig
const sign = switch (n) {
    0 => "zero",
    else => "nonzero",
};
```

For enums, `else` is often unnecessary because the compiler knows all cases.

```zig
const Color = enum {
    red,
    green,
    blue,
};

const text = switch (color) {
    .red => "red",
    .green => "green",
    .blue => "blue",
};
```

If a new enum value is added later, the compiler can point to every switch that must be updated. This is one of the main reasons to prefer a full enum switch over an `else` branch.

Branches may use blocks.

```zig
const price = switch (kind) {
    .small => 10,
    .large => blk: {
        const base = 20;
        const tax = 2;
        break :blk base + tax;
    },
};
```

The block computes the branch value and gives it back with `break`.

All branches must produce compatible types when the switch value is used.

```zig
const x = switch (n) {
    0 => 10,
    1 => 20,
    else => 30,
};
```

This is valid. Every branch gives an integer.

This is wrong:

```zig
const x = switch (n) {
    0 => 10,
    1 => "twenty",
    else => 30,
};
```

One branch gives a string. The others give integers. Zig rejects the program.

A `switch` can also be used only for control flow.

```zig
switch (mode) {
    .debug => std.debug.print("debug\n", .{}),
    .release => std.debug.print("release\n", .{}),
}
```

In this case each branch has type `void`.

`switch` works well with tagged unions. A tagged union stores one value chosen from a set of named alternatives.

```zig
const Token = union(enum) {
    number: i64,
    plus,
    minus,
};

fn printToken(tok: Token) void {
    switch (tok) {
        .number => |n| std.debug.print("number {d}\n", .{n}),
        .plus => std.debug.print("plus\n", .{}),
        .minus => std.debug.print("minus\n", .{}),
    }
}
```

The branch

```zig
.number => |n| ...
```

matches the `number` case and captures its payload in `n`.

This is safer than storing a tag and a value separately. The compiler keeps the tag and payload connected.

A `switch` can also capture the matched value.

```zig
const text = switch (n) {
    0 => "zero",
    1, 2, 3 => |x| blk: {
        _ = x;
        break :blk "small";
    },
    else => "large",
};
```

The captured value is the value that matched the case.

Use `switch` when the shape of the decision matters. Use `if` when the decision is just a boolean test.

```zig
const result = if (n < 10) "small" else "large";
```

This is better as `if`.

```zig
const result = switch (status) {
    .open => "open",
    .closed => "closed",
    .unknown => "unknown",
};
```

This is better as `switch`.

Exercise 3-9. Write a `switch` that converts digits `0` through `9` to their English names.

Exercise 3-10. Write a `switch` over an enum named `Direction` with cases `north`, `south`, `east`, and `west`.

Exercise 3-11. Add a new enum case and observe which switches must change.

Exercise 3-12. Write a tagged union for a simple token: integer, left parenthesis, right parenthesis, plus, and minus. Use `switch` to print each token.

