Home Rust Tutorial: Decision Making in Rust Programming Language

Tutorial: Decision Making in Rust Programming Language

Decision-making in Rust involves controlling the flow of execution based on conditions.

Rust provides constructs like if, else if, else, match, and loops with conditions to implement decision-making logic effectively.

In this tutorial, we will cover:

1. Using if Statements

The if statement executes a block of code if the condition evaluates to true.

Example: Basic if

fn main() {
    let number = 10;

    if number > 5 {
        println!("The number is greater than 5.");
    }
}

2. Combining if with else

The else block runs when the if condition is false.

Example: if and else

fn main() {
    let number = 3;

    if number % 2 == 0 {
        println!("The number is even.");
    } else {
        println!("The number is odd.");
    }
}

3. Using else if for Multiple Conditions

The else if block checks additional conditions.

Example: if, else if, and else

fn main() {
    let score = 85;

    if score >= 90 {
        println!("Grade: A");
    } else if score >= 80 {
        println!("Grade: B");
    } else if score >= 70 {
        println!("Grade: C");
    } else {
        println!("Grade: F");
    }
}

4. Conditional Expressions

In Rust, if can be used as an expression to assign a value to a variable.

Example: if as an Expression

fn main() {
    let age = 20;

    let category = if age >= 18 { "Adult" } else { "Minor" };

    println!("Category: {}", category);
}

5. The match Statement

The match statement is a powerful control flow construct that matches a value against multiple patterns.

Example: Using match

fn main() {
    let day = 3;

    match day {
        1 => println!("Monday"),
        2 => println!("Tuesday"),
        3 => println!("Wednesday"),
        4 => println!("Thursday"),
        5 => println!("Friday"),
        6 | 7 => println!("Weekend"), // Combine patterns
        _ => println!("Invalid day"), // Catch-all case
    }
}

6. Using match with Enums

Enums and match are frequently used together to handle multiple cases.

Example: Matching Enums

enum TrafficLight {
    Red,
    Yellow,
    Green,
}

fn main() {
    let light = TrafficLight::Red;

    match light {
        TrafficLight::Red => println!("Stop"),
        TrafficLight::Yellow => println!("Slow down"),
        TrafficLight::Green => println!("Go"),
    }
}

7. Pattern Matching

Rust's match statement supports complex patterns such as ranges, destructuring, and guards.

7.1 Ranges in match

fn main() {
    let number = 42;

    match number {
        0..=10 => println!("The number is between 0 and 10"),
        11..=50 => println!("The number is between 11 and 50"),
        _ => println!("The number is greater than 50"),
    }
}

7.2 Destructuring in match

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point = Point { x: 10, y: 20 };

    match point {
        Point { x, y: 20 } => println!("x: {}, y is 20", x),
        Point { x, y } => println!("x: {}, y: {}", x, y),
    }
}

7.3 Guards in match

fn main() {
    let number = 15;

    match number {
        n if n % 2 == 0 => println!("The number {} is even", n),
        n if n % 2 != 0 => println!("The number {} is odd", n),
        _ => println!("Unknown number"),
    }
}

8. Practical Examples

8.1 Checking Leap Year

fn main() {
    let year = 2024;

    if year % 4 == 0 {
        if year % 100 != 0 || year % 400 == 0 {
            println!("{} is a leap year.", year);
        } else {
            println!("{} is not a leap year.", year);
        }
    } else {
        println!("{} is not a leap year.", year);
    }
}

8.2 Categorizing Numbers

fn main() {
    let number = 15;

    match number {
        0 => println!("Zero"),
        1..=9 => println!("Single-digit number"),
        10..=99 => println!("Double-digit number"),
        _ => println!("Large number"),
    }
}

8.3 Command-Line Arguments with match

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();

    match args.len() {
        1 => println!("No arguments provided."),
        2 => println!("One argument: {}", args[1]),
        _ => println!("Multiple arguments: {:?}", &args[1..]),
    }
}

8.4 Simplified Calculator

fn main() {
    let a = 10;
    let b = 5;
    let operator = '+';

    let result = match operator {
        '+' => a + b,
        '-' => a - b,
        '*' => a * b,
        '/' => a / b,
        '%' => a % b,
        _ => {
            println!("Invalid operator");
            return;
        }
    };

    println!("Result: {}", result);
}

9. Summary

Construct Use Case
if For simple decision-making based on a single condition.
else if For handling multiple conditions.
else For a default case when all other conditions are false.
match For matching values against multiple patterns, often replacing complex if-else chains.
Guards Adding conditions to patterns for more refined matches.

Key Points

  1. Rust's decision-making constructs ensure safety and expressiveness.
  2. The match statement is powerful and versatile, especially when working with enums and patterns.
  3. Rust encourages exhaustive matches to handle all possible cases.

Practice with these examples to master decision-making in Rust!

You may also like