Debug School

rakesh kumar
rakesh kumar

Posted on

destructuring,guards,binding in rust

Destructuring → To extract values from complex data structures in a clean and concise way.

Guards→ To apply additional conditions while matching so only valid cases are accepted.

Binding→ To capture matched values into variables for immediate and later use.

Short Purpose-Focused Explanation
1️⃣

Destructuring – Why we use it

Makes code shorter and cleaner

Improves readability

Extracts multiple values at once

Reduces manual indexing or field access

Without destructuring: verbose, error-prone
With destructuring: clean and expressive

2️⃣

Guards – Why we use them

Add business rules during matching

Avoid deep if-else nesting

Improve decision clarity

Ensure only valid data flows forward

Guards = “Match this pattern only if condition is true”

3️⃣

Binding – Why we use it

Captures values during matching

Avoids duplicate variable declarations

Makes logic single-pass

Improves performance and clarity

Binding = “Match + store value in one step”

Final Summary (Perfect for notes / W4)

Destructuring → Extract

Guards → Validate

Binding → Store

Destructuring (Pattern Matching)

Theory (simple)

Destructuring means breaking a compound value (tuple/array/struct/enum) into smaller variables using patterns like:

let (a,b) = tuple;

match value { pattern => ... }
Enter fullscreen mode Exit fullscreen mode

1) Destructuring a tuple

fn main() {
    let t = (10, "Hi", true);
    let (a, b, c) = t;

    println!("{}, {}, {}", a, b, c);
}
Enter fullscreen mode Exit fullscreen mode

Output

10, Hi, true
Enter fullscreen mode Exit fullscreen mode

2) Destructuring a struct

#[derive(Debug)]
struct User {
    name: String,
    age: u8,
}

fn main() {
    let u = User { name: "Ashwani".to_string(), age: 27 };

    let User { name, age } = u; // destructure
    println!("name={}, age={}", name, age);
}
Enter fullscreen mode Exit fullscreen mode

Output

name=Ashwani, age=27
Enter fullscreen mode Exit fullscreen mode

Destructuring a tuple struct

#[derive(Debug)]
struct Point(i32, i32);

fn main() {
    let p = Point(5, 7);
    let Point(x, y) = p;

    println!("x={}, y={}", x, y);
}
Enter fullscreen mode Exit fullscreen mode

Output

x=5, y=7
Enter fullscreen mode Exit fullscreen mode

Destructuring an array + slice pattern

fn main() {
    let arr = [1, 2, 3, 4, 5];

    match arr {
        [first, second, .., last] => println!("first={}, second={}, last={}", first, second, last),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

first=1, second=2, last=5
Enter fullscreen mode Exit fullscreen mode

Destructuring an enum

enum Payment {
    Cash(i32),
    Upi { txn_id: String, amount: i32 },
}

fn main() {
    let p = Payment::Upi { txn_id: "TXN99".to_string(), amount: 500 };

    match p {
        Payment::Cash(a) => println!("Cash: {}", a),
        Payment::Upi { txn_id, amount } => println!("UPI {} amount {}", txn_id, amount),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

UPI TXN99 amount 500
Enter fullscreen mode Exit fullscreen mode

Guards (match with conditions)

Theory (simple)

A guard is an extra if condition inside a match arm:

match x {
   pattern if condition => ...
   _ => ...
}

Enter fullscreen mode Exit fullscreen mode

It helps you match only when the condition is true.

1) Guard with integer range

fn main() {
    let x = 15;

    match x {
        n if n < 0 => println!("Negative"),
        n if n <= 10 => println!("0 to 10"),
        _ => println!("Above 10"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

Above 10
Enter fullscreen mode Exit fullscreen mode

2) Guard with tuple

fn main() {
    let p = (0, 7);

    match p {
        (0, y) if y > 0 => println!("On Y-axis above origin: y={}", y),
        (0, y) => println!("On Y-axis y={}", y),
        _ => println!("Not on Y-axis"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

On Y-axis above origin: y=7
Enter fullscreen mode Exit fullscreen mode

3) Guard with enum variant

enum Status {
    Ok(i32),
    Err(String),
}

fn main() {
    let s = Status::Ok(120);

    match s {
        Status::Ok(v) if v >= 100 => println!("High OK: {}", v),
        Status::Ok(v) => println!("Normal OK: {}", v),
        Status::Err(e) => println!("Error: {}", e),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

High OK: 120
Enter fullscreen mode Exit fullscreen mode

4) Guard to filter even/odd

fn main() {
    let n = 8;

    match n {
        x if x % 2 == 0 => println!("Even"),
        _ => println!("Odd"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

Even
Enter fullscreen mode Exit fullscreen mode

5) Guard with string length

fn main() {
    let name = "Ashwani";

    match name {
        s if s.len() > 5 => println!("Long name"),
        _ => println!("Short name"),
    }
}

Enter fullscreen mode Exit fullscreen mode

Output


Long name
Enter fullscreen mode Exit fullscreen mode

Binding (capture values using @)

Theory (simple)

Binding using @ lets you:

capture a matched value

while still checking it matches a pattern/range

Example:

n @ 1..=5
Enter fullscreen mode Exit fullscreen mode

Means:

match range 1 to 5

also store that value in n

1) Bind number within range

fn main() {
    let x = 4;

    match x {
        n @ 1..=5 => println!("In range: {}", n),
        _ => println!("Out of range"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

In range: 4

2) Bind and match enum

enum Login {
    Success(String),
    Failed,
}

fn main() {
    let l = Login::Success("Ashwani".to_string());

    match l {
        s @ Login::Success(_) => println!("Matched success: {:?}", "Success"),
        Login::Failed => println!("Failed"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

Matched success: "Success"

3) Bind with struct field pattern

#[derive(Debug)]
struct Emp {
    id: i32,
    salary: i32,
}

fn main() {
    let e = Emp { id: 101, salary: 90000 };

    match e {
        emp @ Emp { salary: 80000..=100000, .. } => println!("Mid-high employee: {:?}", emp.id),
        _ => println!("Other employee"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

Mid-high employee: 101
Enter fullscreen mode Exit fullscreen mode

4) Bind with tuple patterns

fn main() {
    let t = (3, 9);

    match t {
        pair @ (x, y) if x < y => println!("Increasing pair {:?} ({} < {})", pair, x, y),
        _ => println!("Not increasing"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output


Increasing pair (3, 9) (3 < 9)
Enter fullscreen mode Exit fullscreen mode

5) Bind with slice pattern

fn main() {
    let arr = [10, 20, 30, 40];

    match arr {
        whole @ [10, ..] => println!("Starts with 10: {:?}", whole),
        _ => println!("Different start"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

Starts with 10: [10, 20, 30, 40]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)