Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A tuple pattern is a structural pattern used to destructure and match against tuple types. It allows developers to bind individual elements of a tuple to distinct variables, ignore specific elements, or assert the shape of the data by matching the tuple’s arity and the types of its constituent elements.

Syntax and Arity Matching

A tuple pattern consists of a comma-separated list of sub-patterns enclosed in parentheses. By default, the arity (number of elements) of the tuple pattern must strictly match the arity of the tuple expression being evaluated. Special syntactic rules apply to tuples of arity 0 and 1:
  • Arity 0 (Unit Type): The empty tuple pattern () is used to match the unit type.
  • Arity 1: A single-element tuple pattern must include a trailing comma to distinguish it from a parenthesized pattern. For example, (x,) is a tuple pattern, whereas (x) is simply the pattern x enclosed in parentheses.
// Arity 0: Matching the unit type
let empty = ();
let () = empty;

// Arity 1: Trailing comma is required
let single = (1i32,);
let (x,) = single;

// Arity > 1: Standard comma-separated list
let tuple = (1i32, 2.0f64, "three");
let (x, y, z) = tuple; 

Ignoring Elements

You can selectively ignore elements within a tuple pattern using the wildcard pattern (_) for single elements, or the rest pattern (..) for contiguous sequences of elements. The rest pattern (..) can only be used once per tuple pattern to avoid ambiguity in arity resolution.
let tuple = (1, 2, 3, 4, 5);

// Ignores the second element; arity must still strictly match (5 elements)
let (a, _, c, d, e) = tuple;

// Ignores all elements between the first and the last
let (first, .., last) = tuple;

// Ignores all elements after the first two
let (x, y, ..) = tuple;

Refutability

The refutability of a tuple pattern is entirely dependent on its sub-patterns.
  • Irrefutable: If all sub-patterns within the tuple pattern are irrefutable (e.g., variable bindings or wildcards), the tuple pattern itself is irrefutable and can be used in let statements or function parameters.
  • Refutable: If any sub-pattern is refutable (e.g., matching a specific literal or an enum variant), the entire tuple pattern becomes refutable and must be used in constructs that handle branching, such as match, if let, or while let.
let tuple = (Some(10), 20);

// Refutable pattern: requires `if let` or `match` because `Some(x)` can fail
if let (Some(x), y) = tuple {
    // Executes only if the first element is the `Some` variant
}

// Irrefutable pattern: `_` and `y` will always match
let (_, y) = tuple;

Nesting

Tuple patterns are fully composable. They can be nested inside other tuple patterns, struct patterns, or enum patterns, and can conversely contain any valid sub-pattern.
let nested_tuple = ((1, 2), 3);

// Destructuring a tuple within a tuple
let ((a, b), c) = nested_tuple;

Binding Modes

When destructuring a tuple, binding modes (ref, ref mut, mut) can be applied to individual sub-patterns to control how the memory of the tuple’s elements is accessed or borrowed. If a reference to a tuple is matched, the ref binding mode is implicitly applied to its elements via Rust’s match ergonomics.
let mut tuple = (10, 20);

// `x` is a mutable reference to the first element
// `mut y` is a mutable copy/move of the second element
let (ref mut x, mut y) = tuple;

let tuple_ref = &(30, 40);

// Implicitly borrows elements due to match ergonomics
// `a` and `b` are of type `&i32`
let (a, b) = tuple_ref; 
Master Rust with Deep Grasping Methodology!Learn More