Enums
Enums Are Disjoint Unions
AKA "sum types". Idea is to have a single value represent one of several alternatives
Alternatives can be names, or value-carrying names
Using enum
Alternatives normally carry type-qualified names
enum E { A, B } ... let x = E::A;
but there is a trick:
use E::*; let x = A;
Can impl an enum just as with a struct
enum Point { Point2 { x: u64, y: u64 }, Point3 { x: u64, y: u64, z: u64 }, }
Enum values come in tuple or structured form: tuple is more "normal", becauseā¦
Pattern matching is the only sane way to extract carried values from an enum
Compiler checks that all alternatives are matched, as with other types
The Two Most Important Enums In Rust
Option
enum Option<T> { None, Some(T), } use Option::*; // let x: &u8 = 0; // Compiler says no let x: Option<&u8> = None; match x { None => { Err("missing x") } Some(&x) if x == 7 => { println!("all good"); Ok(()) } Some(&x) => { Err("bad x") } }
Result
Non-Value-Carrying enums Are "Special"
Alternatives have a corresponding usize value
Values start at 0, increase by 1
Can set values for elements (unspecified elements autoincrement, be careful)
Can cast alternative to usize, but no built-in way to convert usize to alternative
enum CLike { A = 5, B, C = 7, } let x = CLike::B as usize; // let y = 6 as CLike; // compiler error
The "Void" enum
What should
enum Void;
mean?let x = // ???
Apparently no inhabitants of this type
Thus, can't really pass it around or whatever
The type "!" is aroundā¦
Why Are Sum Types A Big Deal?
Avoid redundant storage, as with C union
"Tags" are managed by the language, so no tag mismatch issues
Combine (limited) convenience with type and memory safety
"And-or trees" are a thing