# Enums

### Enums

An enum is a type whose values come from a fixed set of names.

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

This declares a type named `Color`. It has three possible values: `red`, `green`, and `blue`.

A value is written with the type name:

```zig
const c = Color.red;
```

When the expected type is known, the type name may be omitted:

```zig
const c: Color = .red;
```

A complete program:

```zig
const std = @import("std");

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

pub fn main() void {
    const c: Color = .green;

    std.debug.print("{}\n", .{c});
}
```

The output is:

```text
.green
```

Enums work well with `switch`.

```zig
const std = @import("std");

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

pub fn main() void {
    const c: Color = .blue;

    const name = switch (c) {
        .red => "red",
        .green => "green",
        .blue => "blue",
    };

    std.debug.print("{s}\n", .{name});
}
```

The output is:

```text
blue
```

The switch must cover all enum values.

If one case is missing, Zig reports an error at compile time.

```zig
const name = switch (c) {
    .red => "red",
    .green => "green",
};
```

This is incomplete because `.blue` is not handled.

A switch may use `else`.

```zig
const name = switch (c) {
    .red => "red",
    else => "other",
};
```

This compiles, but for small enums it is usually better to list every case. That way, adding a new enum value makes the compiler show every place that must be updated.

Enums may have an integer tag type.

```zig
const Status = enum(u8) {
    ok = 0,
    not_found = 1,
    denied = 2,
};
```

Here each enum value has a `u8` integer representation.

The integer value can be obtained with `@intFromEnum`.

```zig
const n = @intFromEnum(Status.not_found);
```

A complete example:

```zig
const std = @import("std");

const Status = enum(u8) {
    ok = 0,
    not_found = 1,
    denied = 2,
};

pub fn main() void {
    const s = Status.not_found;
    const n = @intFromEnum(s);

    std.debug.print("{d}\n", .{n});
}
```

The output is:

```text
1
```

An integer may be converted back with `@enumFromInt`.

```zig
const s: Status = @enumFromInt(1);
```

Use this only when the integer is known to be valid for the enum type. Unknown integer values are a safety problem.

Enums can contain declarations.

```zig
const Direction = enum {
    north,
    south,
    east,
    west,

    pub fn isVertical(self: Direction) bool {
        return switch (self) {
            .north, .south => true,
            .east, .west => false,
        };
    }
};
```

The function belongs to the enum namespace.

```zig
const d: Direction = .north;
const yes = d.isVertical();
```

A complete program:

```zig
const std = @import("std");

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

    pub fn isVertical(self: Direction) bool {
        return switch (self) {
            .north, .south => true,
            .east, .west => false,
        };
    }
};

pub fn main() void {
    const d: Direction = .north;

    std.debug.print("{}\n", .{d.isVertical()});
}
```

The output is:

```text
true
```

An enum value is not a string. It is a distinct value of its enum type.

```zig
const c: Color = .red;
```

The value `c` is not the text `"red"`. It is the enum value `.red`.

This matters when writing APIs. Use strings for external text. Use enums for internal choices.

```zig
const Mode = enum {
    debug,
    release_safe,
    release_fast,
    release_small,
};
```

This is better than passing string names through the program. The compiler checks spelling. The compiler also checks that switches are complete.

Enums may also be inferred in function calls.

```zig
const Mode = enum {
    read,
    write,
};

fn open(mode: Mode) void {
    _ = mode;
}

pub fn main() void {
    open(.read);
}
```

The argument `.read` works because the parameter type is `Mode`.

Use an enum when a value must be one of a known set of alternatives.

Examples:

```zig
const TokenKind = enum {
    identifier,
    number,
    string,
    plus,
    minus,
    eof,
};
```

```zig
const FileState = enum {
    closed,
    open,
    error_seen,
};
```

```zig
const LogLevel = enum {
    debug,
    info,
    warn,
    err,
};
```

An enum gives names to choices. It prevents invalid choices from being represented by accident.

Exercises.

7-13. Define an enum named `Day` with seven values.

7-14. Write a function `isWeekend(day: Day) bool`.

7-15. Define an enum named `LogLevel` and use a `switch` to convert it to a string.

7-16. Define an enum with tag type `u8`, assign explicit integer values, and print one value with `@intFromEnum`.

