🦀 Functional Rust
🎬 Pattern Matching Exhaustive match, destructuring, guards, let-else — compiler-verified branching.
📝 Text version (for readers / accessibility)

• match is exhaustive — the compiler ensures every variant is handled

• Destructuring extracts fields from structs, tuples, and enums in one step

• Guards (if conditions) add extra logic to match arms

• if let and let-else provide concise single-pattern matching

• Nested patterns and @ bindings handle complex data shapes elegantly

561: Or-Patterns — pat1 | pat2

Difficulty: 2 Level: Beginner Match multiple patterns in a single arm using `|`. Reduces repetition when different patterns share the same action.

The Problem This Solves

Without or-patterns, matching several variants with the same handler requires either duplicating the arm body or indirection through a helper function:
match color {
 Color::Red   => "warm",   // duplicate arms
 Color::Yellow=> "warm",   // same body — tedious and easy to miss one
 Color::Green => "cool",
 Color::Blue  => "cool",
 Color::Purple=> "mixed",
}
Or-patterns let you express "any of these → same action" directly in the pattern language, with no duplication.

The Intuition

`pat1 | pat2` reads as "matches if pat1 OR pat2 matches." It's a logical OR on patterns — both branches share the same binding names and must bind the same types. The arm body executes once for whichever pattern matched. Or-patterns work at any nesting level — inside tuples, enums, or other compound patterns. They also work in `if let`, `while let`, and `matches!`.

How It Works in Rust

Enum variant grouping:
#[derive(Debug)]
enum Color { Red, Green, Blue, Yellow, Purple }

fn classify(c: &Color) -> &'static str {
 match c {
     Color::Red | Color::Yellow  => "warm",   // two variants, one arm
     Color::Green | Color::Blue  => "cool",
     Color::Purple               => "mixed",
 }
}
`matches!` macro — boolean test with or-patterns:
fn is_primary(c: &Color) -> bool {
 matches!(c, Color::Red | Color::Green | Color::Blue)
}
Integer or-patterns:
fn describe_number(n: i32) -> &'static str {
 match n {
     0 | 1         => "tiny",
     2 | 3 | 4     => "small",
     5..=9         => "medium",
     _             => "large",
 }
}
Nested or-patterns (inside compound patterns):
enum Shape { Circle(f64), Square(f64), Triangle(f64, f64) }

fn has_single_param(s: &Shape) -> bool {
 matches!(s, Shape::Circle(_) | Shape::Square(_))
}

// Or in a full match with data binding:
fn area_approx(s: &Shape) -> f64 {
 match s {
     Shape::Circle(r) | Shape::Square(r) => r * r, // both bind `r`
     Shape::Triangle(base, height)       => base * height / 2.0,
 }
}
`if let` with or-patterns:
let c = Color::Red;
if let Color::Red | Color::Yellow = c {
 println!("warm color");
}

What This Unlocks

Key Differences

ConceptOCamlRust
Multiple patterns, one arm`pat1pat2 ->` (leading `` optional)`pat1 \pat2 =>` — same syntax, middle `\`
Binding in or-patternsEach alternative must bind same names/typesSame rule — all alternatives must produce same bindings
`matches!` equivalentN/A (inline match or `function`)`matches!(expr, pat1 \pat2)` → `bool`
ExhaustivenessCompiler checks all constructors coveredSame — exhaustiveness checked across all or-pattern arms
Range patterns`0..9 ->` (exclusive)`0..=9 =>` (inclusive) — combinable with `\`
#[derive(Debug)]
enum Color { Red, Green, Blue, Yellow, Purple }

fn classify(c: &Color) -> &'static str {
    match c {
        Color::Red | Color::Yellow  => "warm",
        Color::Green | Color::Blue  => "cool",
        Color::Purple               => "mixed",
    }
}

fn is_primary(c: &Color) -> bool {
    matches!(c, Color::Red | Color::Green | Color::Blue)
}

fn describe_number(n: i32) -> &'static str {
    match n {
        0 | 1         => "tiny",
        2 | 3 | 4     => "small",
        5..=9         => "medium",
        _             => "large",
    }
}

fn main() {
    use Color::*;
    for c in &[Red, Green, Blue, Yellow, Purple] {
        println!("{:?} -> {}", c, classify(c));
    }
    println!("Red primary? {}", is_primary(&Color::Red));
    println!("Yellow primary? {}", is_primary(&Color::Yellow));
    for n in [0, 3, 7, 42] {
        println!("{} is {}", n, describe_number(n));
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test] fn warm() { assert_eq!(classify(&Color::Red), "warm"); }
    #[test] fn cool() { assert_eq!(classify(&Color::Blue), "cool"); }
    #[test] fn primary() { assert!(is_primary(&Color::Red)); assert!(!is_primary(&Color::Yellow)); }
}
(* Or-patterns in OCaml match expressions *)
type color = Red | Green | Blue | Yellow | Purple

let classify c =
  match c with
  | Red | Yellow -> "warm"
  | Green | Blue -> "cool"
  | Purple       -> "mixed"

let is_primary c =
  match c with
  | Red | Green | Blue -> true
  | _                  -> false

let () =
  List.iter (fun c -> Printf.printf "%s\n" (classify c))
    [Red; Green; Blue; Yellow; Purple];
  Printf.printf "Red primary? %b\n" (is_primary Red);
  Printf.printf "Yellow primary? %b\n" (is_primary Yellow)