Currently the autogenerated code uses a macro_rules
macro for parsing input.
macro_rules! parse_input {
($x:expr, $t:ident) => ($x.trim().parse::<$t>().unwrap())
}
This is not very idiomatic and also uses a macro where a regular generic function with some trait bounds would suffice.
I propose the following parse_input
function:
use std::fmt::Debug;
use std::str::FromStr;
fn parse_input<Input, Type>(input: Input) -> Type
where
Type: FromStr,
<Type as FromStr>::Err: Debug,
Input: AsRef<str>,
{
input.as_ref().trim().parse().unwrap()
}
The usage would change from let name = parse_input!(input, TYPE);
to let name: TYPE = parse_input(input);
Let’s take a line from the tutorial as an example:
Before: let dist_1 = parse_input!(input_line, i32); // distance to enemy 1
After: let dist_1: i32 = parse_input(input_line); // distance to enemy 1
Same code of parse_input but with explanations on what it does:
// Additional imports that are required for this to work
use std::fmt::Debug;
use std::str::FromStr;
fn parse_input<Input, Type>(input: Input) -> Type
where
Type: FromStr, // .parse() that has been used in your macro is part of the FromStr trait, so this is required
<Type as FromStr>::Err: Debug, // The .unwrap() panics with a message that contains the debug representation of the error, so the parsing error needs to implement Debug
Input: AsRef<str>, // &str would probably have worked just fine for `input`, but this is more general and makes it work with both `String` and `&str` and even any other type that can be dereferenced as `&str`. This should also potentially make the code easier to generate automatically
{
// This is the same as in your macro, just with an additional `as_ref` to get access to the `&str` type.
input.as_ref().trim().parse().unwrap()
}