5
\$\begingroup\$

This is how I implemented the guessing game - chapter 2 of the Rust book.

use std::io;
use std::io::Error;
use std::cmp::Ordering;
use std::num::ParseIntError;
use rand::Rng;
enum MyReadLineError {
 FailReadLine(Error)
}
#[derive(Debug)]
enum MyReadU32Line {
 FailReadLine(Error),
 FailParse(ParseIntError)
}
fn my_read_line() -> Result<String, MyReadLineError> {
 let mut input = String::new();
 let result = io::stdin().read_line(&mut input);
 match result {
 Ok(_) => Ok(input),
 Err(error ) => Err(MyReadLineError::FailReadLine(error)),
 }
}
fn my_read_u32_line() -> Result<u32, MyReadU32Line> {
 match my_read_line() {
 Result::Ok(line) =>
 match line.trim().parse::<u32>() {
 Ok(value) => Ok(value),
 Err(error) => Err(MyReadU32Line::FailParse(error)),
 }
 Result::Err(MyReadLineError::FailReadLine(error)) => Err(MyReadU32Line::FailReadLine(error)),
 }
}
fn main() {
 println!("Guess the number!");
 let secret_number = rand::thread_rng().gen_range(1, 101);
 loop {
 println!("Please input your guess.");
 let guess = my_read_u32_line();
 match guess {
 Ok (value) => match value.cmp(&secret_number) {
 Ordering::Less => println!("Too small!"),
 Ordering::Greater => println!("Too big!"),
 Ordering::Equal => {
 println!("You win!");
 break;
 },
 }
 Err (_) => println!("Sorry I couldn't read a u32 from your input! Please try again."),
 }
 }
}

This works as expected but I would like to flatten the matches so that doesn't look at verbose, is that possible. Also is there any other way to make that code look better, more readable?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Sep 20, 2020 at 8:58
\$\endgroup\$

1 Answer 1

10
\$\begingroup\$

Welcome to Rust!

Code Formatting

There are some inconsistencies in your formatting — I have run cargo fmt to get rid of them.

Naming

There's no need to prefix everything with My or my_ — in Rust, your names won't as easily clash with existing names as might be the case in certain other languages.

Error handling

For applications, I suggest using the anyhow crate to manage errors — it reduces much of the boilerplate. Just add

anyhow = "1.0"

to the [dependencies] section of your Cargo.toml.

Helper functions

The my_read_line function can be simplified with the ? operator:

use anyhow::Result;
fn read_line() -> Result<String> {
 let mut input = String::new();
 io::stdin().read_line(&mut input)?;
 Ok(input)
}

my_read_u32_line can be similarly simplified:

fn read_u32() -> Result<u32> {
 Ok(read_line()?.trim().parse()?)
}

Magic numbers

We can define constants for the range of the number:

const MIN: u32 = 1;
const MAX: u32 = 100;
// later
let secret_number = rand::thread_rng().gen_range(MIN, MAX + 1);

Organization

I might reorganize the main function to reduce indentation:

loop {
 println!("Please input your guess.");
 let guess = match read_u32() {
 Ok(guess) => guess,
 Err(_) => {
 println!(
 "Sorry I couldn't read a u32 from your input! \
 Please try again."
 );
 continue;
 }
 };
 match guess.cmp(&secret_number) {
 Ordering::Less => println!("Too small!"),
 Ordering::Greater => println!("Too big!"),
 Ordering::Equal => {
 println!("You win!");
 break;
 }
 };
}

Final result

use anyhow::Result;
use rand::Rng;
use std::cmp::Ordering;
use std::io;
const MIN: u32 = 1;
const MAX: u32 = 100;
fn read_line() -> Result<String> {
 let mut input = String::new();
 io::stdin().read_line(&mut input)?;
 Ok(input)
}
fn read_u32() -> Result<u32> {
 Ok(read_line()?.trim().parse()?)
}
fn main() {
 println!("Guess the number!");
 let secret_number = rand::thread_rng().gen_range(MIN, MAX + 1);
 loop {
 println!("Please input your guess.");
 let guess = match read_u32() {
 Ok(guess) => guess,
 Err(_) => {
 println!(
 "Sorry I couldn't read a u32 from your input! \
 Please try again."
 );
 continue;
 }
 };
 match guess.cmp(&secret_number) {
 Ordering::Less => println!("Too small!"),
 Ordering::Greater => println!("Too big!"),
 Ordering::Equal => {
 println!("You win!");
 break;
 }
 };
 }
}
answered Sep 20, 2020 at 14:04
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for your answer, this is really awesome!!! Real nice of you =] \$\endgroup\$ Commented Sep 24, 2020 at 18:44

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.