The Book Guessing Game Issue

Hello,

I am just starting to learn Rust, and I started this journey with The Guessing Game on the Book.
I was a the end where the code is as below :

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;
            }
        }
    }
}

I come from Perl/Lua so I tried to put the creation of the mutable guess String before the Loop to avoid declaring a new variable every time the loop loop. The issue is that read_line from io::stdin append the value and do not replace, so it dosen't work as intended. I looked at the documentation of Stdin and found no method to replace instead of append. Is it impossible ?

Do I have to conclude that using let multiple time in a loop in Rust can't hinder (even slightly) the performance ?

Thanks you.

I looked at the documentation of Stdin and found no method to replace instead of append.

You can call guess.clear() to remove the existing text before reading new text. This is the most efficient option because it can reuse the existing allocation.

However, in code responsible for user interaction, it is not really worth doing such optimizations — the difference in time spent and memory usage is entirely unnoticeable compared to a human user's perception. Feel free to do it anyway (sticking to 'good habits'), but don't complicate your code for the sake of every last bit of performance.

I come from Perl/Lua so I tried to put the creation of the mutable guess String before the Loop to avoid declaring a new variable every time the loop loop.

This is reasonable here, but not a good general principle. "Declaring a new variable" is not a run-time cost — variable scope doesn't exist after the compiler finishes with your program. In this particular case, putting the String::new() outside of the loop would be an optimization, but that's because the String value can reuse its memory allocation, not because the variable is declared outside the loop. (In fact, you could write let mut guess; outside the loop and guess = String::new(); inside the loop — then the variable declaration is outside but it beings you no benefit whatsoever.)

If there is not a specific benefit such as reusing the allocation, you should declare your variables in the smallest scope available. This helps readability and maintainability by keeping declaration close to usage.

3 Likes

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.