liveBook · Manning

Enum

As explained in Refactoring to Rust

An enum is a type whose value is exactly one of a fixed set of named variants, with each variant optionally carrying associated data.

An `enum` is a type with a fixed set of named variants. A value is exactly one of those variants. Use it when a function needs to communicate which of several known outcomes occurred, rather than passing strings that another function must interpret. section 2.5.1

Replace string results with variants

A FizzBuzz helper can return `Fizz`, `Buzz`, `FizzBuzz`, or `NotDivisible` instead of building a string. The caller uses `match` to decide what to print. This keeps the result separate from its display format: the same outcome could be presented differently without parsing a string. section 2.5.1

Listing 2.26 FizzBuzzValue enum holding a number not divisible by 3 or 5
enum FizzBuzzValue {
  Fizz,
  Buzz,
  FizzBuzz,
  NotDivisible(i32),  #1
}

fn main() {
  for i in 1..101 {
    print_fizzbuzz(i);
  }
}

fn print_fizzbuzz(x: i32) {
  match fizzbuzz(x) {
    FizzBuzzValue::FizzBuzz => {
      println!("FizzBuzz");
    }
    FizzBuzzValue::Fizz => {
      println!("Fizz");
    }
    FizzBuzzValue::Buzz => {
      println!("Buzz");
    }
    FizzBuzzValue::NotDivisible(num) => {  #2
      println!("{}", num);
    }
  }
}

fn fizzbuzz(x: i32) -> FizzBuzzValue {
  if x % 3 == 0 && x % 5 == 0 {
    FizzBuzzValue::FizzBuzz
  } else if x % 3 == 0 {
    FizzBuzzValue::Fizz
  } else if x % 5 == 0 {
    FizzBuzzValue::Buzz
  } else {
    FizzBuzzValue::NotDivisible(x)  #3
  }
}

The `NotDivisible(i32)` variant carries the original number. Matching `NotDivisible(num)` gives the printing function that number, so it no longer needs to recover it from a string or use its own input. section 2.5.1

Variants can carry different data. Rust’s `Result<T, E>` is an enum with `Ok(T)` for a successful value and `Err(E)` for an error value. A function that might fail returns a `Result`, and its caller handles success and failure with ordinary control flow. section 2.5.2

Listing 2.27 The definition of the Result type
enum Result<T, E> { #1
    Ok(T),  #2
    Err(E),  #3
}

The declaration shows how one enum can hold either a success value of type `T` or an error value of type `E`. section 2.5.2

A program can also define its own error enum, such as `Error { GotNegative }`, and use it as the error type in `Result`. When a function only needs to pass an error to its caller, `?` replaces an explicit match that returns `Err` early. section 2.5.4

How Refactoring to Rust covers it

How deep it goes
Works from named variants through payloads and match expressions, then applies the same model to Result and custom error types.
Examples
Refactors a FizzBuzz helper from strings to variants, adds a number-carrying variant, and handles negative input with an error enum.
What it assumes
Builds on loops, conditionals, functions, and strings while introducing enum syntax through a small program.
What you can do after
Build it from scratch: define variants, return them from a function, match their payloads, and represent failures with Result.
How it connects
Connects enums to strong typing, pattern matching, Result, error propagation, and the question-mark operator.

Also explained in

Compare how 23 books explain enum →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Refactoring to Rust. The section links point to the parts of the book it draws on.