Rust Beginner : 중첩 된 매치 병합
Sep 20 2020
이것이 내가 추측 게임을 구현 한 방법입니다-Rust 책의 2 장 : https://doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html
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."),
}
}
}
이것은 예상대로 작동하지만 장황하게 보이지 않도록 일치를 평평하게 만들고 싶습니다. 또한 코드를 더보기 좋고 더 읽기 쉽게 만드는 다른 방법이 있습니까?
답변
7 L.F. Sep 20 2020 at 21:04
Rust에 오신 것을 환영합니다!
코드 서식
당신의 서식에 약간의 불일치가 있습니다. 나는 cargo fmt그것들을 제거하기 위해 달려 왔습니다 .
명명
모든 것에 My또는 접두사를 my_붙일 필요가 없습니다. Rust에서는 이름이 다른 특정 언어의 경우처럼 기존 이름과 쉽게 충돌하지 않습니다.
오류 처리
응용 프로그램의 경우 anyhow상자를 사용하여 오류를 관리 하는 것이 좋습니다 . 이렇게하면 상용구를 많이 줄일 수 있습니다. 그냥 추가
anyhow = "1.0"
받는 [dependencies]당신의 섹션 Cargo.toml.
도우미 기능
my_read_line함수는 단순화 될 수 ?연산자
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 유사하게 단순화 할 수 있습니다.
fn read_u32() -> Result<u32> {
Ok(read_line()?.trim().parse()?)
}
매직 넘버
숫자 범위에 대한 상수를 정의 할 수 있습니다.
const MIN: u32 = 1;
const MAX: u32 = 100;
// later
let secret_number = rand::thread_rng().gen_range(MIN, MAX + 1);
조직
main들여 쓰기를 줄이기 위해 함수를 재구성 할 수 있습니다 .
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;
}
};
}
최종 결과
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;
}
};
}
}