Binding and Destructuring in Rust

RustRustBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, the concept of binding in Rust is explored, which allows for indirect access to variables and the ability to branch and use that variable without re-binding. The @ sigil in the match statement is used for binding values to names. Examples are provided, including how to bind values to a specific range and how to "destructure" enum variants like Option.

Note: If the lab does not specify a file name, you can use any file name you want. For example, you can use main.rs, compile and run it with rustc main.rs && ./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("`Rust`")) -.-> rust/DataTypesGroup(["`Data Types`"]) rust(("`Rust`")) -.-> rust/FunctionsandClosuresGroup(["`Functions and Closures`"]) rust(("`Rust`")) -.-> rust/MemorySafetyandManagementGroup(["`Memory Safety and Management`"]) rust(("`Rust`")) -.-> rust/AdvancedTopicsGroup(["`Advanced Topics`"]) rust/DataTypesGroup -.-> rust/integer_types("`Integer Types`") rust/DataTypesGroup -.-> rust/string_type("`String Type`") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("`Function Syntax`") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("`Expressions and Statements`") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("`Lifetime Specifiers`") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("`Traits for Operator Overloading`") subgraph Lab Skills rust/integer_types -.-> lab-99316{{"`Binding and Destructuring in Rust`"}} rust/string_type -.-> lab-99316{{"`Binding and Destructuring in Rust`"}} rust/function_syntax -.-> lab-99316{{"`Binding and Destructuring in Rust`"}} rust/expressions_statements -.-> lab-99316{{"`Binding and Destructuring in Rust`"}} rust/lifetime_specifiers -.-> lab-99316{{"`Binding and Destructuring in Rust`"}} rust/operator_overloading -.-> lab-99316{{"`Binding and Destructuring in Rust`"}} end

Binding

Indirectly accessing a variable makes it impossible to branch and use that variable without re-binding. match provides the @ sigil for binding values to names:

// A function `age` which returns a `u32`.
fn age() -> u32 {
    15
}

fn main() {
    println!("Tell me what type of person you are");

    match age() {
        0             => println!("I haven't celebrated my first birthday yet"),
        // Could `match` 1 ..= 12 directly but then what age
        // would the child be? Instead, bind to `n` for the
        // sequence of 1 ..= 12. Now the age can be reported.
        n @ 1  ..= 12 => println!("I'm a child of age {:?}", n),
        n @ 13 ..= 19 => println!("I'm a teen of age {:?}", n),
        // Nothing bound. Return the result.
        n             => println!("I'm an old person of age {:?}", n),
    }
}

You can also use binding to "destructure" enum variants, such as Option:

fn some_number() -> Option<u32> {
    Some(42)
}

fn main() {
    match some_number() {
        // Got `Some` variant, match if its value, bound to `n`,
        // is equal to 42.
        Some(n @ 42) => println!("The Answer: {}!", n),
        // Match any other number.
        Some(n)      => println!("Not interesting... {}", n),
        // Match anything else (`None` variant).
        _            => (),
    }
}

Summary

Congratulations! You have completed the Binding lab. You can practice more labs in LabEx to improve your skills.

Other Rust Tutorials you may like