Rust

[Rust] Control Flow

llHoYall 2022. 7. 31. 16:12

If you have studied other languages, you can use it almost similarly.

if Expression

if expression allows us to branch code depending on conditions.

fn main() {
    let number = 3;
    
    if number == 1 {
        println!("Number is 1");
    } else if number == 2 {
        println!("Number is 2");
    } else {
        println!("Large number!");
    }
}

The condition in if expression must be a boolean type.

In other words, Rust doesn't have truth and falsy concepts.

fn main() {
    let number = 1;

    if number { // error[E0308]: mismatched types
        println!("Integer types are not allowed");
    }
}

Because if is an expression, we can use it on the right side of a let statement to assign the outcome to a variable.

fn main() {
    let condition = true;
    let number = if condition { 7 } else { 3 };
    println!("Number: {number}"); // Number: 7
}

The values that have the potential to result from each arm of the if must be the same type.

match

match allows us to compare a value against a series of patterns and then execute code based on which pattern matches.

The code associated with each arm is an expression, and the resulting value of the expression in the matching arm is the value that gets returned for the entire match expression.

If we want to run multiple lines of code in a matching arm, we must use curly brackets.

We can specify several patterns using a vertical bar.

And we can use the underscore to math all remaining patterns.

fn main() {
    let dice_roll = 3;

    match dice_roll {
        1 => back(),
        5 | 6 => jump(),
        _ => go(),
    }

    fn go() { println!("Go!"); }
    fn back() { println!("Back!"); }
    fn jump() { println!("Jump!"); }
}

It can bind to the parts of the values that match the pattern.

#[derive(Debug)]
enum SubEnum {
    Sub1,
    Sub2,
}

enum MainEnum {
    Main1,
    Main2,
    MainSub(SubEnum),
}

fn test_func(coin: MainEnum) -> u8 {
    match coin {
        MainEnum::Main1 => 1,
        MainEnum::Main2 => 2,
        MainEnum::MainSub(sub) => {
            println!("{:?}", sub);
            0
        }
    }
}

fn main() {
    test_func(MainEnum::MainSub(SubEnum::Sub2));
}

We can also handle Option<T> using match.

fn main() {
    fn plus_one(x: Option<i32>) -> Option<i32> {
        match x {
            None => None,
            Some(i) => Some(i + 1),
        }
    }

    let seven = plus_one(Some(6));
    let none = plus_one(None);
}

loop

The loop keyword tells Rust to execute a block of code over and over again forever or until you explicitly tell it to stop.

fn main() {
    let mut counter = 0;

    loop {
        println!("{counter}");
        if counter == 5 {
            break;
        }
        counter += 1;
    }
}

We can get the result of the operation out of the loop to the rest of the code.

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;
        if counter == 5 {
            break counter;
        }
    };
    println!("Result: {result}"); // Result: 5
}

If we have loops within loops, break and continue apply to the innermost loop at that point.

We can optionally specify a loop label on a loop that we can then use with break or continue to specify that those keywords apply to the labeled loop instead of the innermost loop.

Loop labels must begin with a single quote.

fn main() {
    let mut counter = 0;

    'outer: loop {
        loop {
            if counter == 5 {
                break;
            }
            if counter == 3 {
                break 'outer;
            }
            counter += 1;
        }
    };
    println!("Counter: {counter}"); // Counter: 3
}

while

It runs a conditional loop, as is used in most languages.

fn main() {
    let mut counter = 0;

    while counter < 5 {
        counter += 1;
    }
    println!("Counter: {counter}"); // Counter: 5
}

for

We can use a for loop and execute some code for each item in a collection.

fn main() {
    let arr = [1, 2, 3, 4, 5];
 
    for elem in arr {
        println!("{elem}");
    }
}

We can run some code a certain number of times.

fn main() {
    for number in (1..5) {
        println!("{number}");
    }
}

If you don't need a loop variable, you can use _ (underscore) to ignore it.

fn main() {
    for _ in 0..3 {
        println!("for loop");
    }
}