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

  • Generics and lifetimes work the same as with structs

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

Examples

http://github.com/pdx-cs-rust/playing-cards

http://github.com/PoHuit/plan-b

Last modified: Monday, 26 April 2021, 11:34 PM