// option1.rs
// Make me compile! Execute `rustlings hint option1` for hints
// you can modify anything EXCEPT for this function's sig
fn print_number(maybe_number: Option<u16>) {
println!("printing: {}", maybe_number.unwrap());
}
fn main() {
print_number(13);
print_number(99);
let mut numbers: [Option<u16>; 5];
for iter in 0..5 {
let number_to_add: u16 = {
((iter * 1235) + 2) / (4 * 16)
};
numbers[iter as usize] = number_to_add;
}
}
前面我们叙述过Option枚举,这里是需要确定print_number()传入的参数是否存在,如果是None,则直接通过unwrap()panic!。所以就在调用print_number的位置的实参加上Some即可。
print_number(Some(13));
print_number(Some(99));
// option2.rs
// Make me compile! Execute `rustlings hint option2` for hints
fn main() {
let optional_word = Some(String::from("rustlings"));
// TODO: Make this an if let statement whose value is "Some" type
word = optional_word {
println!("The word is: {}", word);
} else {
println!("The optional word doesn't contain anything");
}
let mut optional_integers_vec: Vec<Option<i8>> = Vec::new();
for x in 1..10 {
optional_integers_vec.push(Some(x));
}
// TODO: make this a while let statement - remember that vector.pop also adds another layer of Option<T>
// You can stack `Option<T>`'s into while let and if let
integer = optional_integers_vec.pop() {
println!("current value: {}", integer);
}
}
optional_word作为Some(),作为右值赋值给word。所以word也是Some。这个匹配可用if-let完成。会匹配的非常优雅。
如果if let是左值,Some类型为右值绑定,则结构读作:若let将变量解构成Some(i),则执行后面的语句块。如果要指明失败情形,就使用else。这相当于是一个解构的过程。我们可以提供一些额外的失败条件(和Option无关)。
同样,可以用if let匹配任何枚举值,见下面的实例:
let a = Foo::Bar;
let b = Foo::Baz;
let c = Foo::Qux(100);
//变量 a 匹配到了 Foo::Bar
if let Foo::Bar = a {
println!("a is foobar");
}
//变量 b 没有匹配到 Foo::Bar,因此什么也不会打印。
if let Foo::Bar = b {
println!("b is foobar");
}
// 量 c 匹配到了 Foo::Qux,它带有一个值,就和上面例子中的 Some() 类似。
if let Foo::Qux(value) = c {
println!("c is {}", value);
}
另一个好处是if let 允许匹配枚举非参数化的变量,即枚举未注明 #[derive(PartialEq)],我们也没有为其实现PartialEq。在这种情况下,通常if Foo::Bar==a会出错,因为此类枚举的实例不具有可比性。但是,if-let是可行的。
题目中我们是匹配Some的情况,代码如下:
if let Some(word) = optional_word {
println!("The word is: {}", word);
} else {
println!("The optional word doesn't contain anything");
}
接下来是Vector内部元素是Option枚举,所以integar需要套上两层Some。这里用到while-let。 和if-let类似,while-let也可以把别扭的match改写得好看一些。下面提供一个实例:
fn main() {
// 将 `optional` 设为 `Option<i32>` 类型
let mut optional = Some(0);
//这读作:当 let将optional解构成Some(i)时,就
//执行语句块。否则就 `break`。
while let Some(i) = optional {
if i > 9 {
println!("Greater than 9, quit!");
optional = None;
} else {
println!("`i` is `{:?}`. Try again.", i);
optional = Some(i + 1);
}
// ^ 使用的缩进更少,并且不用显式地处理失败情况。
}
//if-let有可选的else/else if分句,
//而while let没有。
}
接下来就很简单了:
while let Some(Some(integer)) = optional_integers_vec.pop() {
println!("current value: {}", integer);
}
运行成功。
// option3.rs
// Make me compile! Execute `rustlings hint option3` for hints
// I AM NOT DONE
struct Point {
x: i32,
y: i32,
}
fn main() {
let y: Option<Point> = Some(Point { x: 100, y: 200 });
match y {
Some(p) => println!("Co-ordinates are {},{} ", p.x, p.y),
_ => println!("no match"),
}
y; // Fix without deleting this line.
}
这里对y的类型是Option,枚举内套用的泛型是经典结构体类型。