Building on top of existing answers, here are a few more observations:
Strange loop
This is obviously correct:
while let None = guess
... but rather weird way to check if an Option is None
. Consider just
while guess.is_none()
Strange guarded match
Yes, you can match guess { x if x < num => ... }
, but that's usually helpful if x
is some part of a binding pattern, not the whole pattern itself. I'd agree if it were Ok(Some(x)) if x < num
, but for a simple pattern an if/else chain is somewhat more obvious:
if guess < num { println!("Your number is too low"); } else if guess > num { println!("Your number is too high"); } else { println!("Correct!"); guessed = true; break; }
Control flow
You had to introduce a guessed
variable just to check whether the loop has exited "normally". Nothing prevents you from using return
in main function:
fn main() { let num = get_num(); for _ in 0..6 { let guess = get_guess(); if guess < num { println!("Your number is too low"); } else if guess > num { println!("Your number is too high"); } else { println!("Correct!"); return; } } println!("Ran out of guesses. The number was {}", num); }
Variable naming
You chose good function names, they convey the meaning perfectly and match the runtime behaviour. My only suggestion would be to replace num
with target
- i32
type already conveys it's a number, the variable name should explain the purpose of it. The same applies to get_num
function.
Personal preference: match vs transformations
I would rather write
guess: Option<i32> = None; // ... guess = buffer .trim() .parse() .inspect_err(|_| println!("Invalid guess; try again")) .ok();
Note that a) I moved the i32
annotation to the definition site so that .parse
can be used unqualified, and b) I rewrote match
with native Result
methods. To me this reads a bit easier: .ok()
transforms a Result to an Option, and inspect_error
contains something we want to do if the result was Err
. But the early return approach in @kmdreko answer is even nicer as it avoids a complicated Result-Option-inner value conversion.
Similarly, your last .expect("Can't be reached")
should be .unwrap()
: it doesn't accept a message string and better conveys the meaning of "I'm absolutely confident this should always pass" while .expect("Message")
is closer to "This shouldn't normally happen, but here's a helpful message if it somehow does".