๐Ÿฆ€ 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

571: `..` and `_` Wildcards

Difficulty: 2 Level: Beginner Ignore fields, elements, and bindings you don't need in pattern matches.

The Problem This Solves

Rust's patterns are exhaustive by design โ€” you must account for every field and variant. But often you only care about one or two fields in a large struct, or the first and last elements of a tuple. Writing out every field name just to ignore most of them is verbose and brittle: adding a field to the struct breaks every match site. `..` ("dot-dot") and `_` ("underscore") solve this. `..` in a struct pattern skips all remaining fields. `..` in a tuple pattern matches any number of elements in the middle. `_` ignores a single binding (and suppresses unused-variable warnings). Together they make patterns concise without sacrificing exhaustiveness.

The Intuition

`_` is a throwaway slot: "put something here but I don't want it." `..` is a throwaway range: "skip everything else I didn't name." In struct patterns, `..` means "I only named the fields I care about; let the rest be whatever." In tuples, `(first, .., last)` says "give me the first and last; the middle doesn't matter." The `_x` convention (leading underscore) binds the variable to suppress warnings, unlike bare `_` which doesn't bind at all โ€” useful when you want the name for documentation clarity but the value isn't used yet.

How It Works in Rust

1. Struct `..` โ€” `Config { host, port, .. }` in a function parameter destructures only `host` and `port`; all other fields are silently ignored. 2. Enum variant `_` โ€” `Response::Ok(v, _, _)` extracts the first field and ignores the others by position. 3. Tuple `..` โ€” `let (first, .., last) = (1, 2, 3, 4, 5)` binds first and last; middle elements are discarded. 4. Function parameter `_` โ€” `fn always_zero(_: i32) -> i32 { 0 }` accepts the argument but doesn't bind it. 5. `_x` suppression โ€” `let _unused = String::from("...");` binds without triggering unused-variable lint.

What This Unlocks

Key Differences

ConceptOCamlRust
Ignore a field`_` in pattern; records use `{ field; _ }``_` for single field; `..` to skip all remaining struct fields
Tuple remainder`(first, _)` or `(first, _rest)``(first, .., last)` โ€” `..` matches any number of middle elements
Unused binding`_x` convention in OCaml too`_x` or `_` โ€” `_x` binds, `_` doesn't
ExhaustivenessCompiler warns on missing casesSame; `..` satisfies exhaustiveness for remaining struct fields
struct Config { host: String, port: u16, timeout: f64, debug: bool }

fn connect(Config { host, port, .. }: &Config) {
    println!("Connecting to {}:{}", host, port);
}

#[derive(Debug)]
enum Response { Ok(i32, String, f64), Err(String) }

fn get_val(r: &Response) -> Option<i32> {
    match r {
        Response::Ok(v, _, _) => Some(*v),
        Response::Err(_)      => None,
    }
}

fn main() {
    let cfg = Config { host:"localhost".into(), port:8080, timeout:30.0, debug:true };
    connect(&cfg);

    for r in [Response::Ok(42,"msg".into(),1.0), Response::Err("oops".into())] {
        match get_val(&r) {
            Some(v) => println!("Got: {}", v),
            None    => println!("Error"),
        }
    }

    // _ in function param
    fn always_zero(_: i32) -> i32 { 0 }
    println!("zeros: {:?}", (0..5).map(always_zero).collect::<Vec<_>>());

    // .. in tuple
    let (first, .., last) = (1, 2, 3, 4, 5);
    println!("first={} last={}", first, last);

    // _x: bind but suppress warning
    let _unused = String::from("won't warn");
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test] fn test_get_val() {
        assert_eq!(get_val(&Response::Ok(7,"x".into(),0.0)), Some(7));
        assert_eq!(get_val(&Response::Err("e".into())), None);
    }
    #[test] fn tuple_wildcard() { let (f,..,l) = (1,2,3,4,5); assert_eq!((f,l),(1,5)); }
}
(* Wildcards in OCaml *)
type config = { host: string; port: int; timeout: float; debug: bool }

let connect { host; port; _ } =
  Printf.printf "Connecting to %s:%d\n" host port

type response = Ok of int * string * float | Err of string

let get_val = function
  | Ok (v, _, _) -> Some v
  | Err _        -> None

let () =
  let cfg = { host="localhost"; port=8080; timeout=30.0; debug=true } in
  connect cfg;
  List.iter (fun r ->
    match get_val r with
    | Some v -> Printf.printf "Got: %d\n" v
    | None   -> Printf.printf "Error\n"
  ) [Ok(42,"msg",1.0); Err "oops"]