速成课第3节-练习解答
下面是上一节 Rust 速成课 “迭代器和错误” 中的练习题的解决方案。
这篇文章是基于 FP 完成 Rust 教学系列的一部分。 如果你在博客之外阅读这篇文章,你可以在介绍文章的顶部找到这个系列中所有文章的链接。 也可订阅 RSS 频道。
练习1
这里的诀窍是用 Skip 数据类型“包裹” Args 数据类型:
use std::env::{args, Args};
use std::iter::Skip;
fn main() {
let args: Skip<Args> = args().skip(1);
for arg in args {
println!("{}", arg);
}
}
您可能已经注意到,我们不需要将 args 标记为可变的。 这是因为我们将 args 值移动到 for 循环中,这意味着在 main 函数中看不到 for 循环对其进行的任何变更。
练习2
当我们在该示例的上下文中调用 parse 时,类型推断告诉我们,width 和 height 结果必须为 u32,因为它们在 Frame 中用作字段。 Rust 能够根据所需的返回类型决定使用什么实现。 酷!
Haskellers 再次翻白眼并说“老新闻”。
练习3
完整的源文件:
#[derive(Debug)]
struct Frame {
width: u32,
height: u32,
}
#[derive(Debug)]
enum ParseError {
TooFewArgs,
TooManyArgs,
InvalidInteger(String),
}
struct ParseArgs(std::env::Args);
impl ParseArgs {
fn new() -> ParseArgs {
ParseArgs(std::env::args())
}
fn require_arg(&mut self) -> Result<String, ParseError> {
match self.0.next() {
None => Err(ParseError::TooFewArgs),
Some(s) => Ok(s),
}
}
fn require_no_args(&mut self) -> Result<(), ParseError> {
match self.0.next() {
Some(_) => Err(ParseError::TooManyArgs),
None => Ok(()),
}
}
}
fn parse_u32(s: String) -> Result<u32, ParseError> {
match s.parse() {
Err(_) => Err(ParseError::InvalidInteger(s)),
Ok(x) => Ok(x),
}
}
fn parse_args() -> Result<Frame, ParseError> {
let mut args = ParseArgs::new();
// skip the command name
args.require_arg()?;
let width_str = args.require_arg()?;
let height_str = args.require_arg()?;
args.require_no_args()?;
let width = parse_u32(width_str)?;
let height = parse_u32(height_str)?;
Ok(Frame { width, height })
}
fn main() {
println!("{:?}", parse_args());
}
练习4
我们希望确保宽度和高度的最小尺寸。 首先,让我们在 ParseError 枚举中添加两个变量:
WidthTooSmall(u32),
HeightTooSmall(u32),
然后将下面的代码添加到 parse_args 函数中,就在 Ok 之前:
if width < 2 {
return Err(WidthTooSmall(width));
}
if height < 2 {
return Err(HeightTooSmall(height));
}
练习5
这是我们提出尾 ? 的另一个完美时机!
fn main () -> Result<(), self::parse_args::ParseError> {
let frame = parse_args::parse_args()?;
let mut game = Game::new(frame);
let sleep_duration = std::time::Duration::from_millis(33);
loop {
println!("{}", game);
game.step();
std::thread::sleep(sleep_duration);
}
}
最后更新于
这有帮助吗?