Regarding the expression followed by a semicolon

fn main(){
    let mut number_start_from = 0;
    println!("Previous number is {number_start_from}");

    'change_number: loop {
        number_start_from += 1; //semicolon
        println!("Latest number is {number_start_from}");

        if number_start_from == 5 {
            break 'change_number; //semicolon
        }
    }
}

There’s something I’m curious about: if an expression like number_start_from += 1 is followed by a semicolon, it become a statement.

According to the book, it will not return a value to the variable let mut number_start_from = 0;. I need to add a semicolon because the next line of code is println!("Previous number is {number_start_from}");. If not, the expression would be read as incomplete and it would confuse my compiler.

Why does this happen? Will the expression still return a value even if it uses a semicolon?

The syntax of a block is '{' item* expr? '}': braces around any number of "items" and an optional final expression (handwaving some details) which serves as the value of the block as a whole, and the most common "item" is a "statement expression", which has the syntax expr ';', an expression followed by a semicolon. The effect of this is that adding a semicolon means you can put more items after the expression, but also that it no longer serves as the final expression.

Separate to this, the break statement has the syntax 'break' label? expr? ';', which breaks out of a containing loop, with the value of the expression.

Finally, the loop statement is also valid as an expression (one of the details handwaved above), but this only matters if it has a type other than the default, empty type () (also known as the unit type, because it only has one value), which happens when you break with a value.

There's a lot going on in that example!

1 Like

Thank you, got it

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.