patternrustTip
Enum variants with data: type-safe tagged unions
Viewed 0 times
enumvariantstagged unionalgebraic data typesmake impossible states impossiblepattern matching
Problem
Developers model complex states with structs and boolean flags instead of using enum variants with data, leading to invalid state combinations.
Solution
Use enum variants with data to make invalid states unrepresentable:
// Bad: boolean flags allow invalid combinations
struct Connection {
is_connected: bool,
is_authenticated: bool, // meaningless if not connected
address: Option<String>,
}
// Good: enum variants hold only relevant data
#[derive(Debug)]
enum Connection {
Disconnected,
Connected { address: String },
Authenticated { address: String, user_id: u64 },
}
// Each variant holds exactly the data it needs
#[derive(Debug)]
enum Shape {
Circle { radius: f64 },
Rectangle { width: f64, height: f64 },
Triangle { base: f64, height: f64 },
}
impl Shape {
fn area(&self) -> f64 {
match self {
Shape::Circle { radius } => std::f64::consts::PI * radius * radius,
Shape::Rectangle { width, height } => width * height,
Shape::Triangle { base, height } => 0.5 * base * height,
}
}
}Why
Enum variants with data implement the 'make impossible states impossible' principle. The type system enforces that data only exists in contexts where it is meaningful, eliminating entire classes of runtime errors.
Gotchas
- Enum variants are not types themselves — you cannot write fn process(s: Shape::Circle) { ... }
- Tuple variants Shape::Circle(f64) and struct variants Shape::Circle { radius: f64 } are both valid — prefer named fields for clarity
- Enums with large variant data waste memory as every value allocates enough for the largest variant — Box<T> can help
Revisions (0)
No revisions yet.