下面是上一节 Rust 速成课 “ 迭代器和闭包三规则” 中练习题的解决方案。
这篇文章是基于 完成 Rust 教学系列的一部分。 如果你在博客之外阅读这篇文章,你可以在 找到这个系列中所有文章的链接。 也可 频道。
练习1
复制 fn double(x: &mut u32) {
*x *= 2;
}
fn main() {
let mut x = 5;
double(&mut x);
println!("{}", x);
}
注意,变量 x 不需要是可变的,因为我们只修改它引用的值。
练习2
(IMO)直截了当的解决办法是:
复制 struct InfiniteUnit;
impl IntoIterator for InfiniteUnit {
type Item = ();
type IntoIter = InfiniteUnitIter;
fn into_iter(self) -> Self::IntoIter {
InfiniteUnitIter
}
}
struct InfiniteUnitIter;
impl Iterator for InfiniteUnitIter {
type Item = ();
fn next(&mut self) -> Option<()> {
Some(())
}
}
fn main() {
let mut count = 0;
for _ in InfiniteUnit {
count += 1;
println!("count == {}", count);
if count >= 5 {
break;
}
}
}
但是,如果你想更聪明一点,在标准库中已经有一个函数可以创建一个无限迭代器,叫做 repeat。 使用它,您可以绕过这里的额外结构:
复制 struct InfiniteUnit;
impl IntoIterator for InfiniteUnit {
type Item = ();
type IntoIter = std::iter::Repeat<()>;
fn into_iter(self) -> Self::IntoIter {
std::iter::repeat(())
}
}
fn main() {
let mut count = 0;
for _ in InfiniteUnit {
count += 1;
println!("count == {}", count);
if count >= 5 {
break;
}
}
}
练习3
闭包版本:
复制 fn main() {
let msg: &str = "Hi!";
let say_hi = |msg| println!("{}", msg);
say_hi(msg);
say_hi(msg);
}
函数版本:
复制 fn main() {
let msg: &str = "Hi!";
fn say_hi(msg: &str) {
println!("{}", msg);
}
say_hi(msg);
say_hi(msg);
}
因为 say_hi 不引用局部作用域中的任何变量,所以它不需要是闭包。
练习4
复制 fn main() {
call_with_hi(say_message);
call_with_hi(say_message);
}
fn say_message(msg: &str) {
println!("{}", msg);
}
fn call_with_hi<F>(f: F)
where F: Fn(&str)
{
f("Hi!");
}
练习5
我们得到的第一个错误消息是:
复制 rror[E0599]: no method named `map` found for type `std::vec::Vec<u32>` in the current scope
--> main.rs:5:23
|
5 | for i in nums.map(unimplemented!()) {
| ^^^
|
= note: the method `map` exists but the following trait bounds were not satisfied:
`&mut std::vec::Vec<u32> : std::iter::Iterator`
`&mut [u32] : std::iter::Iterator`
看来我们需要一个迭代器了。 我们有三种不同的选择: into_iter()、 iter() 和 iter_ mut ()。 由于我们需要多次使用结果,并且不需要任何变异,iter() 似乎是正确的选择。 一旦我们用 nums.iter () 替换nums.iter().map,我们可以进入 unimplemented!() 位。
我们需要一个数字翻倍的结局。 这很简单: | x | x * 2。 把这个放进去就行了! 额外的挑战: 闭包是 FnOnce,FnMut,还是 Fn?
练习6
您需要在 create 调用上添加一个 .unwrap()调用:
复制 use std::io::Write;
let mut file = std::fs::File::create("mylog.txt").unwrap();
file.write_all(b"I was clicked.\n");
这样,您将收到来自编译器的警告,告知您已忽略来自 write_all 的 Result。 这是不好的做法,编译器理应会向您大喊大叫。 您可以使用unwrap() 修复该问题。 但是,这也是一种不好的做法:)。
练习7
复制 extern crate gtk;
use gtk::prelude::*;
use gtk::{Button, Window, WindowType};
use std::cell::RefCell;
use std::io::Write;
fn main() -> Result<(), Box<std::error::Error>> {
gtk::init()?;
let window = Window::new(WindowType::Toplevel);
window.set_title("First GTK+ Program");
window.set_default_size(350, 70);
let button = Button::new_with_label("Click me!");
window.add(&button);
window.show_all();
window.connect_delete_event(|_, _| {
gtk::main_quit();
Inhibit(false)
});
let file = std::fs::File::create("mylog.txt")?;
let file = RefCell::new(file);
button.connect_clicked(move |_| {
match file.borrow_mut().write_all(b"I was clicked.\n") {
Ok(()) => (),
Err(e) => eprintln!("Error writing to file: {}", e),
}
});
gtk::main();
Ok(())
}