Enums & Pattern Matching — A Powerful Evolution of Symbol and case/when
Rust enums can carry data — a concept Ruby doesn't have
In Ruby, you use Symbols for states. :active, :inactive, :pending. Rust's enum fills this role.
enum Status {
Active,
Inactive,
Pending,
}
let s = Status::Active;
So far, similar to Ruby Symbols. But the real power of Rust enums: each variant can carry data.
Data-carrying enums
enum Message {
Quit, // no data
Text(String), // one String
Move { x: i32, y: i32 }, // named fields
Color(u8, u8, u8), // multiple values
}
let msg = Message::Text(String::from("hello"));
let pos = Message::Move { x: 10, y: 20 };
In Ruby, you'd need class inheritance or Hashes for this. In Rust, one enum expresses "this type is one of these shapes."
match — forced exhaustive matching
Maps to Ruby's case/when, but you must handle every case.
# Ruby — no else is fine
case status
when :active then "active"
when :inactive then "inactive"
# missing :pending — no error
end
// Rust — missing case = compile error
match status {
Status::Active => "active",
Status::Inactive => "inactive",
Status::Pending => "pending", // omit this → error[E0004]
}
Why is this great? When you add a new variant to an enum, every match gets a compile error. You never miss an unhandled case.
Extracting data in match
match msg {
Message::Quit => println!("quit"),
Message::Text(text) => println!("text: {}", text),
Message::Move { x, y } => println!("move: ({}, {})", x, y),
Message::Color(r, g, b) => println!("color: {},{},{}", r, g, b),
}
Extract data from inside the enum while branching simultaneously. Like doing type checking and data extraction in one case/when.
if let — check just one case
While match handles all cases, if let checks just one.
if let Message::Text(text) = msg {
println!("text: {}", text);
}
// rest is ignored
Feels like Ruby's if status == :active, but with data extraction included.
Option and Result are enums
Option<T> is Some(T) or None. Result<T, E> is Ok(T) or Err(E). Both are enums. Rust's error handling is built on top of enums.
Key Points
enum is Ruby Symbol groups evolved — can carry data
match is enhanced case/when — must handle every case exhaustively
match extracts data and branches simultaneously
Option and Result are enums — foundation of Rust error handling
Pros
- ✓ Adding a variant makes the compiler find every unhandled location
- ✓ Data-carrying enums are more concise than Ruby class inheritance
Cons
- ✗ More boilerplate than Ruby Symbols for lightweight use
- ✗ Forced exhaustive matching in match feels tedious at first