Rust: Advanced Rust Pattern Matching

Last updated: 2026-08-26

Pattern matching is one of Rust’s most powerful language features, and advanced techniques such as match guards, @ bindings, and multiple patterns allow you to exercise more fine-grained control over your matches—not just “matching values,” but “matching conditions.”

If basic pattern matching is like a multiple-choice question (choosing one branch to execute), then advanced pattern matching is like a composite question—you can check values, bind references, and evaluate additional conditions all at the same time.


1. What You'll Learn



2. A Story About an Employee Performance Rating

(1) The Struggle: Using an if-else chain for a comprehensive rating

Tom is the company's HR manager, and he needs to assign comprehensive ratings based on employees' performance scores and attendance records.

The rules are as follows:

Level Performance Score Attendance Requirements
A+ ≥95 Perfect attendance (≥22 days)
A ≥85 Attendance ≥ 20 days
B ≥70 Attendance ≥ 18 days
C ≥60
D <60

At first, he wrote a long string of if-else:

RUST
fn rate_employee(score: u32, attendance: u32) -> &'static str {
    if score >= 95 && attendance >= 22 {
        "A+"
    } else if score >= 85 && attendance >= 20 {
        "A"
    } else if score >= 70 && attendance >= 18 {
        "B"
    } else if score >= 60 {
        "C"
    } else {
        "D"
    }
}

Although this code runs, it has several issues: the conditions are scattered throughout a chain of if-else statements, making it hard to read, and there is no exhaustive check—if rating rules are added in the future, it would be easy to overlook them. Furthermore, the coupling between scores and attendance is not clear enough.

(2) Advanced Approaches to Pattern Matching in Rust

RUST
fn rate_employee(score: u32, attendance: u32) -> &'static str {
    match score {
        // Guard Requirements: Meeting the Score Requirement + Attendance Requirements Met
        s if s >= 95 && attendance >= 22 => "A+",
        s if s >= 85 && attendance >= 20 => "A",
        s if s >= 70 && attendance >= 18 => "B",
        s if s >= 60 => "C",
        _ => "D",  // Fallback: score < 60
    }
}

fn main() {
    let employees = [
        ("Alice", 98, 23),
        ("Bob", 88, 21),
        ("Charlie", 88, 17),  // High scores but insufficient attendance
        ("Diana", 72, 19),
        ("Eve", 55, 20),
    ];

    for (name, score, attendance) in &employees {
        let rating = rate_employee(*score, *attendance);
        println!("{:8} | Score: {:2} | Attendance: {:2} days | Rating: {}",
            name, score, attendance, rating);
    }
}

Output:

TEXT 📖 Display only
Alice    | Score: 98 | Attendance: 23 days | Rating: A+
Bob      | Score: 88 | Attendance: 21 days | Rating: A
Charlie  | Score: 88 | Attendance: 17 days | Rating: B
Diana    | Score: 72 | Attendance: 19 days | Rating: B
Eve      | Score: 55 | Attendance: 20 days | Rating: D

match The guard makes the conditions for each branch immediately clear: the "AND" relationship between score and attendance is clearly visible. _ The catch-all branch ensures exhaustiveness. Furthermore, the semantics of s if s >= ... for different score ranges are more intuitive than those of else if.



3. Overview of Advanced Pattern Matching

(1) Concept Map

100%
graph TB
    A[Advanced Pattern Matching] --> B[match Guard]
    A --> C[@ Bind]
    A --> D[Multimode |]
    A --> E[Range Matching]
    A --> F[matches! Macro]
    A --> G[Deconstruction Patterns]
    B --> B1["match x { n if n > 10 => ... }"]
    C --> C1["match x { e @ 1..=5 => ... }"]
    D --> D1["match x { 1 | 3 | 5 => ... }"]
    E --> E1["match x { 1..=10 => ... }"]
    F --> F1["if matches!(x, 1..=5) { ... }"]
    G --> G1["let Point { x, y } = p;"]
    G --> G2["match opt { Some(v @ 1..=10) => ... }"]

(2) Comparison of Matching Methods

Method Syntax When to Use Example
Basic match match x { PAT => .. } Simple value match match x { 1 => "one" }
match guard match x { PAT if COND => .. } Match + additional conditions n if n > 10 && n % 2 == 0
@ Binding e @ PAT => .. Binding value when matched e @ 1..=10 => e
Multi-mode | PAT1 | PAT2 => .. Multiple modes share the same branch 1 | 3 | 5 => "odd"
Range ..= PAT1..=PAT2 => .. Matches a range of values 1..=5 => "small"
matches! macro matches!(x, PAT) Boolean result only if matches!(x, 1..=5)
Deconstruction let PAT = value Decomposing Composite Types let (a, b) = pair

(3) Quick Reference for Pattern Types

Pattern Type Syntax Match Target Example
Literal 1 / "hello" Exact Value match x { 1 => ... }
Variable Binding x Any value, bound to x match x { n => ... }
Wildcard _ Any value, ignored match x { _ => ... }
Multi-mode 1 | 2 | 3 Multiple values match x { 1 | 2 => ... }
Range 1..=5 Closed interval range match x { 1..=5 => ... }
Deconstructing Tuples (a, b) Tuples match pair { (x, y) => ... }
Deconstructing Structures Point { x, y } Structures match p { Point { x, y } => ... }
Deconstructing Enumerations Some(v) Enumeration Variants match opt { Some(v) => ... }
@ Binding e @ 1..=10 Range + Binding match x { e @ 1..=10 => ... }
Guard x if x > 0 Mode + Conditions match x { n if n > 0 => ... }
Ignore the rest .. Ignore some fields match p { Point { x, .. } => ... }


4. Advanced Matching Examples

▶ Example 1: Match Guard + @ Binding + Multi-Mode (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
  [@ binding] score <s> captured for A+ rating
  [@ binding] score <s> captured for A rating
  [@ binding] score <s> captured for B rating
  [guard] score <s> is below 60, rating D
  [wildcard] unexpected combination
<emp.name>:
  Rating: <rating>, Bonus: <bonus>%, Special: <special>
RUST
// ============================================
// Comprehensive Example: Employee Performance Rating System
// Display match Guard, @ Bind, Multi-pattern
// ============================================

#[derive(Debug)]
enum Department {
    Engineering,
    Sales,
    HR,
    Management,
}

#[derive(Debug)]
struct Employee {
    name: String,
    score: u32,
    attendance: u32,
    department: Department,
}

impl Employee {
    /// Rate employee using advanced pattern matching.
    /// Returns (rating, bonus_percentage).
    fn rate(&self) -> (&'static str, u32) {
        match (self.score, self.attendance) {
            // @ binding: capture the matched score value
            s @ 95..=100 if self.attendance >= 22 => {
                println!("  [@ binding] score {} captured for A+ rating", s);
                ("A+", 30)
            }
            s @ 85..=94 if self.attendance >= 20 => {
                println!("  [@ binding] score {} captured for A rating", s);
                ("A", 20)
            }
            s @ 70..=84 if self.attendance >= 18 => {
                println!("  [@ binding] score {} captured for B rating", s);
                ("B", 10)
            }
            // Multi-pattern: 60..=69 OR exactly 70 with low attendance
            60..=69 | 70..=84 => {
                ("C", 5)  // No @ binding needed here
            }
            // match guard with combined conditions
            s if s < 60 => {
                println!("  [guard] score {} is below 60, rating D", s);
                ("D", 0)
            }
            // Catch-all: should not reach normally
            _ => {
                println!("  [wildcard] unexpected combination");
                ("Unknown", 0)
            }
        }
    }

    /// Check if this employee qualifies for special bonus
    /// using matches! macro.
    fn has_special_bonus(&self) -> bool {
        // matches! returns true if the pattern matches
        matches!(self.department, Department::Engineering | Department::Management)
            && self.score >= 90
    }
}

fn main() {
    let employees = vec![
        Employee {
            name: String::from("Alice"),
            score: 97,
            attendance: 23,
            department: Department::Engineering,
        },
        Employee {
            name: String::from("Bob"),
            score: 88,
            attendance: 21,
            department: Department::Sales,
        },
        Employee {
            name: String::from("Charlie"),
            score: 88,
            attendance: 17,
            department: Department::HR,
        },
        Employee {
            name: String::from("Diana"),
            score: 65,
            attendance: 20,
            department: Department::HR,
        },
        Employee {
            name: String::from("Eve"),
            score: 42,
            attendance: 15,
            department: Department::Management,
        },
    ];

    for emp in &employees {
        println!("{}:", emp.name);
        let (rating, bonus) = emp.rate();
        let special = emp.has_special_bonus();
        println!("  Rating: {}, Bonus: {}%, Special: {}",
            rating, bonus, special);
        println!();
    }
}

Output:

TEXT 📖 Display only
Alice:
  [@ binding] score 97 captured for A+ rating
  Rating: A+, Bonus: 30%, Special: true

Bob:
  [@ binding] score 88 captured for A rating
  Rating: A, Bonus: 20%, Special: false

Charlie:
  [@ binding] score 88 captured for B rating
  Rating: B, Bonus: 10%, Special: false

Diana:
  Rating: C, Bonus: 5%, Special: false

Eve:
  [guard] score 42 is below 60, rating D
  Rating: D, Bonus: 0%, Special: true

This example comprehensively demonstrates three advanced matching techniques: @ binds captured values for later use; if uses guards to add additional conditions (such as attendance requirements); | uses multimode to allow different ranges to share the same branch; and matches! uses a macro to concisely determine "whether it belongs to one of several variants."


▶ Example 2: Deconstructing Nested Structures and Enums (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
  [range] High priority task (level <task.priority>)
  [nested destructure] Task #<id> '<title>' completed by <reviewer> at <finished_at> (priority <priority>)
  [@ binding] Task '<task.title>' blocked by <blocked_by>: <reason>
  [guard] Important in-progress task (priority <priority>)
  [wildcard] Task '<task.status>': status <task.title>
Task #<task.id>: <task.title>
RUST
// ============================================
// Nested Deconstruction: Matching Enums in Structures, Tuples in Enumerations
// ============================================

#[derive(Debug)]
enum TaskStatus {
    Pending,
    InProgress,
    Completed { finished_at: String, reviewer: String },
    Blocked { reason: String, blocked_by: String },
}

#[derive(Debug)]
struct Task {
    id: u32,
    title: String,
    status: TaskStatus,
    priority: u8,  // 1 (highest) to 5 (lowest)
}

fn analyze_task(task: &Task) {
    // Destructure the Task struct directly in match
    match task {
        // Multi-pattern: priority 1 or 2 with any status
        Task { priority: 1..=2, .. } => {
            println!("  [range] High priority task (level {})", task.priority);
        }
        // Destructure both Task and TaskStatus::Completed
        Task {
            id,
            title,
            status:
                TaskStatus::Completed {
                    finished_at,
                    reviewer,
                },
            priority,
        } => {
            println!("  [nested destructure] Task #{} '{}' completed by {} at {} (priority {})",
                id, title, reviewer, finished_at, priority);
        }
        // Destructure TaskStatus::Blocked with @ binding on reason
        Task {
            status:
                TaskStatus::Blocked {
                    reason,
                    blocked_by,
                },
            ..
        } => {
            println!("  [@ binding] Task '{}' blocked by {}: {}",
                task.title, blocked_by, reason);
        }
        // Match guard on enum variant
        Task {
            status: TaskStatus::InProgress,
            priority,
            ..
        } if *priority <= 3 => {
            println!("  [guard] Important in-progress task (priority {})", priority);
        }
        // Wildcard for remaining
        _ => {
            println!("  [wildcard] Task '{}': status {:?}", task.title, task.status);
        }
    }
}

fn main() {
    let tasks = vec![
        Task {
            id: 1,
            title: String::from("Security audit"),
            status: TaskStatus::Completed {
                finished_at: String::from("2026-07-01"),
                reviewer: String::from("Alice"),
            },
            priority: 1,
        },
        Task {
            id: 2,
            title: String::from("Update dependencies"),
            status: TaskStatus::Blocked {
                reason: String::from("Waiting for approval"),
                blocked_by: String::from("Manager"),
            },
            priority: 2,
        },
        Task {
            id: 3,
            title: String::from("Write documentation"),
            status: TaskStatus::InProgress,
            priority: 3,
        },
        Task {
            id: 4,
            title: String::from("Fix typo in README"),
            status: TaskStatus::Pending,
            priority: 5,
        },
    ];

    for task in &tasks {
        println!("Task #{}: {}", task.id, task.title);
        analyze_task(task);
        println!();
    }
}

Output:

TEXT 📖 Display only
Task #1: Security audit
  [nested destructure] Task #1 'Security audit' completed by Alice at 2026-07-01 (priority 1)

Task #2: Update dependencies
  [range] High priority task (level 2)

Task #3: Write documentation
  [guard] Important in-progress task (priority 3)

Task #4: Fix typo in README
  [wildcard] Task 'Fix typo in README': status Pending

Nested destructuring is a powerful feature of Rust’s pattern matching: you can destruct structs, enums, and tuples simultaneously within a single match branch. .. ignores fields you’re not interested in, and @ binds and captures inner values. Note that Task { priority: 1..=2, .. } matches tasks with any priority of 1 or 2—because although Blocked comes later in the pattern, range matches tasks with priority=2 first.


▶ Example 3: Combining the matches! macro with if let (Difficulty: ⭐⭐)

Output:

TEXT 📖 Display only
<status>:
  is_success: <is_success(status)>
  is_server_error: <is_server_error(status)>
  is_redirect_to_301: <is_redirect_to(status, 301)>
  category: <categorize(status)>
  >> Server error code: <code>
RUST
// ============================================
// matches! Macro: Simple Boolean Pattern Matching
// ============================================

#[derive(Debug, PartialEq)]
enum HttpStatus {
    Ok,
    NotFound,
    ServerError(u16),
    Redirect(u16),
}

/// Check if a status is a success (2xx).
fn is_success(status: &HttpStatus) -> bool {
    matches!(status, HttpStatus::Ok)
}

/// Check if a status is a server error (5xx).
fn is_server_error(status: &HttpStatus) -> bool {
    matches!(status, HttpStatus::ServerError(_))
}

/// Check if a status is a redirect (3xx) with specific code.
fn is_redirect_to(status: &HttpStatus, code: u16) -> bool {
    matches!(status, HttpStatus::Redirect(c) if *c == code)
}

/// Get status category using multiple matches! checks.
fn categorize(status: &HttpStatus) -> &'static str {
    if matches!(status, HttpStatus::Ok) {
        "Success"
    } else if matches!(status, HttpStatus::Redirect(301 | 302)) {
        "Temporary Redirect"
    } else if matches!(status, HttpStatus::Redirect(_)) {
        "Other Redirect"
    } else if matches!(status, HttpStatus::NotFound) {
        "Not Found (404)"
    } else if matches!(status, HttpStatus::ServerError(500..=599)) {
        "Server Error"
    } else {
        "Unknown"
    }
}

fn main() {
    let statuses = vec![
        HttpStatus::Ok,
        HttpStatus::NotFound,
        HttpStatus::Redirect(301),
        HttpStatus::Redirect(307),
        HttpStatus::ServerError(500),
        HttpStatus::ServerError(503),
    ];

    for status in &statuses {
        println!("{:?}:", status);
        println!("  is_success: {}", is_success(status));
        println!("  is_server_error: {}", is_server_error(status));
        println!("  is_redirect_to_301: {}", is_redirect_to(status, 301));
        println!("  category: {}", categorize(status));

        // if let with matches!-style pattern
        if let HttpStatus::ServerError(code) = status {
            println!("  >> Server error code: {}", code);
        }
        println!();
    }
}

Output:

TEXT 📖 Display only
Ok:
  is_success: true
  is_server_error: false
  is_redirect_to_301: false
  category: Success

NotFound:
  is_success: false
  is_server_error: false
  is_redirect_to_301: false
  category: Not Found (404)

Redirect(301):
  is_success: false
  is_server_error: false
  is_redirect_to_301: true
  category: Temporary Redirect

Redirect(307):
  is_success: false
  is_server_error: false
  is_redirect_to_301: false
  category: Other Redirect

ServerError(500):
  is_success: false
  is_server_error: true
  is_redirect_to_301: false
  category: Server Error

ServerError(503):
  is_success: false
  is_server_error: true
  is_redirect_to_301: false
  category: Server Error

The matches! macro returns a bool, which is suitable for pattern matching in if conditions. It supports all pattern syntax, including if guards, multiple patterns, and range matching. Unlike if let, matches! does not bind variables; it only returns true/false—it is the most concise option when you only need to evaluate a condition without retrieving a value.


▶ Example 4: Comprehensive Exercise—Expression Evaluator (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
Expression<s>: <val> = <i + 1>
Expression<i + 1>: <s> = Error (Division by Zero)
RUST
// ============================================
// Comprehensive Example: Implementing Expression Evaluation Using Nested Pattern Matching
// ============================================

#[derive(Debug, Clone)]
enum Expr {
    Number(f64),
    Add(Box<Expr>, Box<Expr>),
    Sub(Box<Expr>, Box<Expr>),
    Mul(Box<Expr>, Box<Expr>),
    Div(Box<Expr>, Box<Expr>),
    Neg(Box<Expr>),
}

fn eval(expr: &Expr) -> Option<f64> {
    match expr {
        Expr::Number(n) => Some(*n),
        Expr::Add(a, b) => Some(eval(a)? + eval(b)?),
        Expr::Sub(a, b) => Some(eval(a)? - eval(b)?),
        Expr::Mul(a, b) => Some(eval(a)? * eval(b)?),
        Expr::Div(a, b) => {
            let divisor = eval(b)?;
            if divisor == 0.0 { None } else { Some(eval(a)? / divisor) }
        }
        Expr::Neg(a) => Some(-eval(a)?),
    }
}

fn expr_to_string(expr: &Expr) -> String {
    match expr {
        Expr::Number(n) => format!("{:.0}", n),
        Expr::Add(a, b) => format!("({} + {})", expr_to_string(a), expr_to_string(b)),
        Expr::Sub(a, b) => format!("({} - {})", expr_to_string(a), expr_to_string(b)),
        Expr::Mul(a, b) => format!("({} * {})", expr_to_string(a), expr_to_string(b)),
        Expr::Div(a, b) => format!("({} / {})", expr_to_string(a), expr_to_string(b)),
        Expr::Neg(a) => format!("-{}", expr_to_string(a)),
    }
}

fn main() {
    let expr1 = Expr::Add(
        Box::new(Expr::Number(10.0)),
        Box::new(Expr::Mul(Box::new(Expr::Number(3.0)), Box::new(Expr::Number(4.0)))),
    );
    let expr2 = Expr::Div(
        Box::new(Expr::Sub(Box::new(Expr::Number(20.0)), Box::new(Expr::Number(5.0)))),
        Box::new(Expr::Number(3.0)),
    );
    let expr3 = Expr::Neg(Box::new(Expr::Number(42.0)));
    let expr4 = Expr::Div(Box::new(Expr::Number(10.0)), Box::new(Expr::Number(0.0)));

    let exprs = [expr1, expr2, expr3, expr4];
    for (i, expr) in exprs.iter().enumerate() {
        let s = expr_to_string(expr);
        match eval(expr) {
            Some(val) => println!("Expression{}: {} = {:.2}", i + 1, s, val),
            None => println!("Expression{}: {} = Error (Division by Zero)", i + 1, s),
        }
    }
}

Output:

TEXT 📖 Display only
Expression1: (10 + (3 * 4)) = 22.00
Expression2: ((20 - 5) / 3) = 5.00
Expression3: -42 = -42.00
Expression4: (10 / 0) = Error (Division by Zero)

Recursive enumeration combined with nested destructuring is one of the most powerful applications of pattern matching. Box<Expr> Allows enumerations to reference themselves (since Box is a fixed-size pointer). eval Uses the ? operator to elegantly propagate non-zero errors.


▶ Example 5: Pattern Matching and JSON-like Data Structures (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
Type: <type_name(&data)>
Number of nodes: <deep_count(&data)>
Name: <name>
Average Score: <avg>
City: <city>
RUST
// ============================================
// Processing Dynamically Typed Data Using Pattern Matching
// ============================================

#[derive(Debug, Clone)]
enum Value {
    Null,
    Bool(bool),
    Number(f64),
    String(String),
    Array(Vec<Value>),
    Object(Vec<(String, Value)>),
}

fn type_name(val: &Value) -> &str {
    match val {
        Value::Null => "null",
        Value::Bool(_) => "bool",
        Value::Number(_) => "number",
        Value::String(_) => "string",
        Value::Array(_) => "array",
        Value::Object(_) => "object",
    }
}

fn deep_count(val: &Value) -> usize {
    match val {
        Value::Array(items) => items.iter().map(deep_count).sum::<usize>() + 1,
        Value::Object(entries) => entries.iter().map(|(_, v)| deep_count(v)).sum::<usize>() + 1,
        _ => 1,
    }
}

fn find_key<'a>(val: &'a Value, key: &str) -> Option<&'a Value> {
    match val {
        Value::Object(entries) => entries.iter().find(|(k, _)| k == key).map(|(_, v)| v),
        _ => None,
    }
}

fn main() {
    let data = Value::Object(vec![
        ("name".into(), Value::String("Alice".into())),
        ("age".into(), Value::Number(30.0)),
        ("active".into(), Value::Bool(true)),
        ("scores".into(), Value::Array(vec![
            Value::Number(95.0),
            Value::Number(88.0),
            Value::Number(92.0),
        ])),
        ("address".into(), Value::Object(vec![
            ("city".into(), Value::String("Beijing".into())),
            ("zip".into(), Value::Number(100000.0)),
        ])),
    ]);

    println!("Type: {}", type_name(&data));
    println!("Number of nodes: {}", deep_count(&data));

    if let Some(Value::String(name)) = find_key(&data, "name") {
        println!("Name: {}", name);
    }

    if let Some(Value::Array(scores)) = find_key(&data, "scores") {
        let avg: f64 = scores.iter()
            .filter_map(|v| if let Value::Number(n) = v { Some(*n) } else { None })
            .sum::<f64>() / scores.len() as f64;
        println!("Average Score: {:.1}", avg);
    }

    if let Some(Value::Object(addr)) = find_key(&data, "address") {
        if let Some(Value::String(city)) = find_key(&Value::Object(addr.clone()), "city") {
            println!("City: {}", city);
        }
    }
}

Output:

TEXT 📖 Display only
Type: object
Number of nodes: 11
Name: Alice
Average Score: 91.7
City: Beijing

Use enumerations to simulate dynamically typed data (such as JSON), and safely extract and iterate through it using pattern matching. find_key Use if let for secure access, and filter_map combined with pattern matching to filter and transform values in an array.


❓ FAQ

Q How is the precedence between a match guard (if guard) and a match branch determined?
A A match guard is a condition within a branch—the pattern is matched first, then the guard is evaluated. If the guard returns false, the program proceeds to the next branch (it does not fall-through to the next one!). Variables bound by the pattern match can be used in the guard condition.
Q What is the difference between @ binding and using a variable directly?
A @ binding captures a value while matching a specific pattern. For example, e @ 1..=10 means "if the value is between 1 and 10, bind that value to e." Writing x directly matches any value and binds it to x. @ allows you to restrict the range while still using that value.
Q What is the difference between .. and _ in pattern matching?
A .. matches any number of elements (and ignores them), while _ matches a single position. When destructuring a struct, Struct { a, .. } ignores all other fields; in a tuple, (x, .., z) matches the first and last elements. _ ignores only one position. .. can only be used once in the same pattern.
Q What is the difference between the matches! macro and if let?
A matches! returns a bool (without binding a variable), while if let binds a variable and executes the code block. If you only need to check “whether it matches” without needing the matched value, use matches!. If you need to destruct the value and use it, use if let or match.
Q Multi-mode | Can it be used with different enum variants?
A Yes, but the variants must have the same type and number of data elements (or none at all). For example, Some(1) | Some(2) is acceptable, but Some(1) | None is not, because Some has data elements while None does not.
Q Which types are supported for range matching ..=?
A Any integer type that implements PartialOrd (i8-u128, u8-u128) and char are supported. For example, match c { 'a'..='z' => "lowercase", 'A'..='Z' => "uppercase", _ => "other" }. Range matching for f64 is not supported.

📖 Summary


📝 Exercises

  1. Difficulty ⭐: Write a function fn describe_number(n: i32) -> &'static str that uses match and range matching: 1..=10 returns "small," 11..=100 returns "medium," 101..=1000 returns "large," and all others return "out of range." Test with 5, 50, 500, and 5000 in the main function.

  2. Difficulty ⭐⭐: Define an enumeration Temperature that includes two variants: Celsius(f64) and Fahrenheit(f64). Write a function fn describe_temp(temp: &Temperature) -> &'static str that uses the matches! macro and the if guard to determine: if Celsius is greater than 30 or Fahrenheit is greater than 86, return "hot"; if Celsius is less than 0 or Fahrenheit is less than 32, return "cold"; otherwise, return "moderate". Test the four temperatures in the main function.

  3. Difficulty ⭐⭐⭐: Define a struct Order that contains id: u32, items: Vec<String>, total: f64, and status: OrderStatus (enumeration: Pending, Shipped { tracking: String }, Delivered { date: String }). Implement a method fn summary(&self) -> String that uses nested destructuring and match guards to return different summary messages based on the status and total amount (e.g., for shipped orders where the total amount is greater than 1,000, display "High-value order shipped, tracking: xxx"). In the main function, create three orders and print their summaries.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏