Enums

Represent a closed set of named states and use match to handle each variant.

1

Core concepts

enum, variants, match, exhaustiveness

2

How the learner should approach this project

Do not paste the complete program immediately. Create the file, type the first step, run vpp check, and then run the program when a complete entry point exists. Read the explanation before looking at the snippet. After each step, predict what the new code should do. This turns the page into a lesson rather than a code dump.

3

Step 1: Define TrafficLight

An enum represents one value chosen from a fixed set of variants. The compiler knows the complete set, which makes exhaustive matching possible.

After typing the snippet, identify the new names introduced by the step. Ask what each name represents, what type the compiler should infer or check, and what value should exist after the code runs.

main.vpp
enum TrafficLight {
    Red
    Yellow
    Green
}
4

Step 2: Put the enum inside a struct

A struct field can use a user defined enum type. Signal now represents a value that carries a TrafficLight.

Before moving forward, explain how this step connects to the previous one. In particular, identify which values cross a function boundary, which values change, and which values are guaranteed by the type system.

main.vpp
struct Signal {
    light: TrafficLight
}
5

Step 3: Match every variant

match inspects signal.light and selects the arm corresponding to the active variant. Every TrafficLight variant is covered, so the match is exhaustive.

Before moving forward, explain how this step connects to the previous one. In particular, identify which values cross a function boundary, which values change, and which values are guaranteed by the type system.

main.vpp
fn action(signal: Signal) -> string {
    match signal.light {
        Red => {
            return "stop"
        }
        Yellow => {
            return "slow"
        }
        Green => {
            return "go"
        }
    }
}
6

Step 4: Construct and evaluate signals

The main function creates two Signal values and sends them through action. The returned strings show how enum state can drive program behavior.

Before moving forward, explain how this step connects to the previous one. In particular, identify which values cross a function boundary, which values change, and which values are guaranteed by the type system.

main.vpp
fn main() -> int {
    let stop = Signal { light: Red }
    let go = Signal { light: Green }
    print(action(stop))
    print(action(go))
    return 0
}
7

Complete source

main.vpp
enum TrafficLight {
    Red
    Yellow
    Green
}
struct Signal {
    light: TrafficLight
}
fn action(signal: Signal) -> string {
    match signal.light {
        Red => {
            return "stop"
        }
        Yellow => {
            return "slow"
        }
        Green => {
            return "go"
        }
    }
}
fn main() -> int {
    let stop = Signal { light: Red }
    let go = Signal { light: Green }
    print(action(stop))
    print(action(go))
    return 0
}
8

Expected behavior

The complete program should produce the following output when run with the command shown below. Exact formatting should follow the current V++ runtime.

stop
go
9

Run the project

terminal
vpp run projects/07-enums/main.vpp
10

What the learner should understand after this project

Enums model a closed set of states. match makes those states visible in code and lets the compiler reason about coverage.

11

Common mistakes to teach

  1. Leaving an enum variant out of match
  2. Using a variant that belongs to another enum
  3. Constructing a struct with an incompatible enum value
12

Practice extension

Add a fourth traffic state and observe which match sites the compiler requires you to update.

A strong learner should be able to explain the program without looking at the code, rebuild the core idea from memory, and make the practice change without copying a solution.

13

Full program

main.vpp
enum TrafficLight {
    Red
    Yellow
    Green
}
struct Signal {
    light: TrafficLight
}
fn action(signal: Signal) -> string {
    match signal.light {
        Red => {
            return "stop"
        }
        Yellow => {
            return "slow"
        }
        Green => {
            return "go"
        }
    }
}
fn main() -> int {
    let stop = Signal { light: Red }
    let go = Signal { light: Green }
    print(action(stop))
    print(action(go))
    return 0
}
vpp
$ ready. Click Test program.