Enums
Enums (enumerations) define a type that can be one of several named variants. Each variant can carry different data, making enums ideal for representing values that are one of a fixed set of possibilities.
Basic Syntax
Section titled “Basic Syntax”Define an enum with the enum keyword:
enum Direction { North, South, East, West,}Each name inside the braces is a variant. Variants with no attached data are called unit variants.
Unit Variants
Section titled “Unit Variants”Unit variants carry no payload. Construct them with EnumName::VariantName:
let dir = Direction::North
match dir { Direction::North => print("heading north"), Direction::South => print("heading south"), Direction::East => print("heading east"), Direction::West => print("heading west"),}Tuple Variants
Section titled “Tuple Variants”A tuple variant carries a single unnamed value:
enum Shape { Circle(number), Square(number), Rectangle(number, number),}
let s = Shape::Circle(5.0)let r = Shape::Rectangle(3.0, 4.0)Extract the payload with pattern matching:
fn area(s: Shape) -> number { match s { Shape::Circle(r) => 3.14159 * r * r, Shape::Square(side) => side * side, Shape::Rectangle(w, h) => w * h, }}
print(area(Shape::Circle(5.0))) // 78.53975print(area(Shape::Rectangle(3.0, 4.0))) // 12.0Struct-Style Variants
Section titled “Struct-Style Variants”Variants can also carry named fields:
enum Message { Quit, Move { x: int, y: int }, Write(string), ChangeColor { r: int, g: int, b: int },}
let msg = Message::Move { x: 10, y: 20 }Match on struct-style variants by name:
fn handle(msg: Message) { match msg { Message::Quit => print("quit"), Message::Move { x, y } => print(f"move to ({x}, {y})"), Message::Write(text) => print(f"write: {text}"), Message::ChangeColor { r, g, b } => print(f"color rgb({r},{g},{b})"), }}Exhaustive Pattern Matching
Section titled “Exhaustive Pattern Matching”match on an enum must cover every variant. The compiler enforces this:
enum Color { Red, Green, Blue }
let c = Color::Red
// This compiles — all three variants are covered:match c { Color::Red => print("red"), Color::Green => print("green"), Color::Blue => print("blue"),}If you miss a variant, the compiler reports a non-exhaustive match error.
The Wildcard _
Section titled “The Wildcard _”Use _ to match any remaining variants when you don’t need to handle them all:
enum Status { Active, Inactive, Pending, Banned }
let s = Status::Pending
match s { Status::Active => print("active"), _ => print("not active"),}_ must be the last arm — it matches anything not already covered.
Built-in Enums: Option and Result
Section titled “Built-in Enums: Option and Result”Shape’s standard library defines two fundamental enums you will encounter throughout the language.
Option<T>
Section titled “Option<T>”Represents a value that may or may not be present:
enum Option<T> { Some(T), None,}Use it instead of null:
fn find_first(v: Vec<number>, predicate: (number) -> bool) -> Option<number> { for x in v { if predicate(x) { return Some(x) } } None}
let result = find_first([1, 2, 3, 4, 5], |x| x > 3)
match result { Some(val) => print(f"found: {val}"), None => print("not found"),}Result<T, E>
Section titled “Result<T, E>”Represents either success (Ok) or failure (Err):
enum Result<T, E> { Ok(T), Err(E),}The ? operator propagates errors automatically — see
Error Handling for details.
fn parse_port(s: string) -> Result<int, string> { let n = s.to_int()? if n < 1 or n > 65535 { return Err(f"port out of range: {n}") } Ok(n)}
match parse_port("8080") { Ok(port) => print(f"listening on port {port}"), Err(msg) => print(f"invalid: {msg}"),}Auto-Derived Display
Section titled “Auto-Derived Display”Enums automatically derive a Display implementation that prints the variant
name. For unit variants this is just the name; for tuple and struct variants,
the payload is included:
let d = Direction::Northprint(d) // "North"
let s = Shape::Circle(3.0)print(s) // "Circle(3.0)"Override Display by implementing to_string() on the enum if you need custom
formatting.
See Also
Section titled “See Also”- Pattern Matching — exhaustive matching, guards, and nested patterns
- Variables and Types — type annotations and inference
- Error Handling —
Result,Option, and the?operator