Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I end an expression with ; inside a loop?

Tags:

rust

I just started learning Rust and I often have some questions that I can't find any answer. I don't really know how and where to post my question, so I'll try SO.

I started to read the Rust documentation on the website and I did the Guessing game example.

I realized that the match cmp expression inside the loop could be turned into a statement and everything still works. So I wonder why and what version should really be preferred?

use rand::Rng;
use std::cmp::Ordering;
use std::io;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {}", guess);

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        } // <=== here should it be ended as statement (;) or not?
    }
}
like image 525
JCorriveau Avatar asked May 30 '20 12:05

JCorriveau


2 Answers

match, if, loop, and other expressions that have {} blocks are treated specially by the Rust compiler. When these expressions occur as expression statements, that is, not as part of a larger expression, and the type of the expression that has the block is (), you do not have to put ; after it to separate it from a following statement.

This is not the case for expression statements without blocks, which always must be separated from the following statement (if one exists) by ;, even if their type is ().

Because this rule exists, it is usual in Rust not to put ; after match, if, unsafe, etc. when they are used only for side effects, or after for and while loops (which are always used only for side effects, since they always return ()).

That said, both rustfmt and Clippy seem to be fine with the extra ;, so if you prefer it there for aesthetic reasons, you're unlikely to offend anyone by using it.

like image 92
trent Avatar answered Nov 14 '22 12:11

trent


In Rust, loop blocks expect a "return" type of the empty type (). This is the type that's returned when you end with a statement and don't return anything at all (e.g. {f();}). println! returns the empty type, so the code you posted works either way, however I would say it makes more sense to end it with a semicolon.

like image 1
Aplet123 Avatar answered Nov 14 '22 12:11

Aplet123