Return a value from labeled loops
Asked Answered
K

1

6

We can return a value from loops with break, for example:

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    println!("The result is {result}");
}

And we can break the outer loops using labels, but is there a way to also return a value while breaking outer loops?

fn main() {
    let mut count = 0;
    'counting_up: loop {
        println!("count = {count}");
        let mut remaining = 10;

        loop {
            println!("remaining = {remaining}");
            if remaining == 9 {
                break;
            }
            if count == 2 {
                break 'counting_up; // <-- Want to retun a value here
            }
            remaining -= 1;
        }

        count += 1;
    }
    println!("End count = {count}");
}

Kalmia answered 10/7, 2022 at 10:45 Comment(2)
It's not exactly clear what you mean by "return". You can break 'counting_up 42; and assign like let foo = 'counting_up: loop { ... }.... Is that what you mean?Electrum
@Electrum yes, thank you, it's not mentioned in the same page doc.rust-lang.org/book/ch03-05-control-flow.htmlKalmia
E
9

Loops in Rust are expressions, and while most loops evaluate to (), you can break with a value, including breaking to outer labels. In the following example, this is accomplished by break 'counting_up Some(1) and assigning the loop's value via let foo: Option<usize> = 'counting_up: loop {

Notice that the compiler will enforce that all control flow paths evaluate to the same type (that is, the type of foo). If your loop does not produce a value in all cases, you can simply use Option, as in the example below.

fn main() {
    let mut count = 0;

    // Assign the loop's value to `foo`
    let foo: Option<usize> = 'counting_up: loop {
        println!("count = {count}");
        let mut remaining = 10;

        loop {
            println!("remaining = {remaining}");
            if remaining == 9 {
                break;
            }
            if count == 2 {
                // Value found
                break 'counting_up Some(1);
            }
            if count == 3 {
                // Break early, assign `None` to `foo`
                break 'counting_up None;
            }
            remaining -= 1;
        }

        count += 1;

        if count >= 42 {
            // break from 'counting_loop, assign `None` to `foo`
            break None;
        }
    };

    println!("End count = {foo:?}");
}
Electrum answered 10/7, 2022 at 11:10 Comment(1)
You should include a link to the Rust reference: doc.rust-lang.org/reference/expressions/….Underhanded

© 2022 - 2024 — McMap. All rights reserved.