Ruta graveolens  ·  notes from a language experiment  ·  cultivated since 2025

Enums

Enums define types with a fixed set of possible values, called variants.

Defining Enums

enum Color {
    Red,
    Green,
    Blue,
}

fn main() -> i32 {
    let c = Color.Green;
    0
}

Variants are accessed with a .: EnumName.VariantName.

Matching on Enums

Use match to handle each variant:

const std = @import("std");

enum Color {
    Red,
    Green,
    Blue,
}

fn color_value(c: Color) -> i32 {
    match c {
        Color.Red => 1,
        Color.Green => 2,
        Color.Blue => 3,
    }
}

fn main() -> i32 {
    println(@to_string(color_value(Color.Red)));    // prints: 1
    println(@to_string(color_value(Color.Green)));  // prints: 2
    println(@to_string(color_value(Color.Blue)));   // prints: 3
    0
}

Exhaustive Matching

Match expressions on enums must be exhaustive—you must handle all variants:

enum Direction {
    North,
    South,
    East,
    West,
}

fn to_degrees(d: Direction) -> i32 {
    match d {
        Direction.North => 0,
        Direction.East => 90,
        Direction.South => 180,
        Direction.West => 270,
    }
}

fn main() -> i32 {
    to_degrees(Direction.North)
}

If you forget a variant, the compiler will tell you:

fn to_degrees(d: Direction) -> i32 {
    match d {
        Direction.North => 0,
        Direction.East => 90,
        // Error: non-exhaustive match, missing South and West
    }
}

Enums in Structs

Enums can be fields in structs:

enum Status {
    Pending,
    Active,
    Completed,
}

struct Task {
    id: i32,
    status: Status,
}

fn is_done(task: Task) -> bool {
    match task.status {
        Status.Completed => true,
        _ => false,
    }
}

fn main() -> i32 {
    let task = Task {
        id: 1,
        status: Status.Active,
    };

    if is_done(task) {
        println("task is done");
    } else {
        println("task is not done");  // this branch runs: status is Active
    }
    0
}

Example: Simple State Machine

enum TrafficLight {
    Red,
    Yellow,
    Green,
}

fn next_light(current: TrafficLight) -> TrafficLight {
    match current {
        TrafficLight.Red => TrafficLight.Green,
        TrafficLight.Green => TrafficLight.Yellow,
        TrafficLight.Yellow => TrafficLight.Red,
    }
}

fn light_duration(light: TrafficLight) -> i32 {
    match light {
        TrafficLight.Red => 30,
        TrafficLight.Yellow => 5,
        TrafficLight.Green => 25,
    }
}

fn main() -> i32 {
    light_duration(next_light(TrafficLight.Red))
}