-1

In the following snippet, break counter * 2 ending with ; or not, would not affect it returns value 20. It is different from what I find in rust online book, which says expression must not end with ;.

What is more unbelievable is, {} is said to be an expression, it is true in loop but not while, so the last println! throws an error like cannot format which I guess counter is an empty tuple. But I think counter should be integer 0.

fn loop_flow() {
    let mut counter = 0;
    let a = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2
        }
    }; 
    println!("value a is {}", a);

    let counter = while counter != 0 {
        counter -= 1;
        counter
    }

    println!("counter: {} should be 0", counter);

}
Tiina
  • 4,285
  • 7
  • 44
  • 73
  • Where is the while version for comparison? – NomadMaker Dec 03 '20 at 10:13
  • First question has an answer here: [Break with or without semicolon](https://stackoverflow.com/questions/65024479/why-does-break-not-need-a-semicolon-when-ending-a-loop). – Mihir Luthra Dec 03 '20 at 10:16
  • [`for` and `while` only return `()`](https://github.com/rust-lang/rfcs/issues/1767#issuecomment-292678002). – Mihir Luthra Dec 03 '20 at 10:25
  • @NomadMaker there isn't such in tutorial. When I saw `let a = loop` I wonder `let a = while` – Tiina Dec 04 '20 at 01:32
  • 1
    @Mihir Thanks! I guess the reasons are under aggreement. But this inconsistent performance confuses a new learner, like me. – Tiina Dec 04 '20 at 02:17

1 Answers1

0

In the following snippet, break counter * 2 ending with ; or not, would not affect it returns value 20. It is different from what I find in rust online book, which says expression must not end with ;.

Like return, break is more of a statement than an expression: it never actually returns anything itself instead it jumps out of a body (function and loop respectively).

What is more unbelievable is, {} is said to be an expression, it is true in loop but not while, so the last println! throws an error like cannot format which I guess counter is an empty tuple. But I think counter should be integer 0.

A lone block:

let a = { 1 };

is an expression.

In a loop or while, however, {} is a "body" and the rules are completely different. While a while is an expression, it doesn't and can't return anything useful since the body could execute 0 times. Thus the result of a while is always ().

In fact, not only does rustc complain that it can not format (), it first complains that the "result" of a while body must be ():

error[E0308]: mismatched types
  --> src/lib.rs:13:9
   |
11 |       let counter = while counter != 0 {
   |  ___________________-
12 | |         counter -= 1;
13 | |         counter
   | |         ^^^^^^^ expected `()`, found integer
14 | |     };
   | |     -- help: consider using a semicolon here
   | |_____|
   |       expected this to be `()`

This is documented:

Like the for expression, we can use break and continue. A while expression cannot break with a value and always evaluates to () unlike loop.

Masklinn
  • 34,759
  • 3
  • 38
  • 57