Rust 新手编程/模式匹配
外观
我们之前创建了 AngleType 枚举。假设我们想打印一些关于角度的解释。为了根据遇到的枚举变体来改变这个解释,我们可以使用 match 语句。例如
fn print_angle_info(points: Points) {
match points.angle_type {
AngleType::Acute => {
println!("This angle is an acute angle; one of less than 90 degrees!");
},
AngleType::Right(axis_aligned) => {
if axis_aligned {
println!("This angle is an axis-aligned right angle, exactly 90 degrees!");
} else {
println!("This angle is a non axis-aligned right angle, exactly 90 degrees!");
}
},
AngleType::Obtuse => {
println!("This angle is an obtuse one. That means it more than 90 degrees, but less than 180.");
},
AngleType::Reflex => {
println!("This angle is a reflex angle. That means it's very large: more than 180 degrees :O");
}
}
}
如果角度类型是每个代码块中描述的类型,那么我们就进入那个代码块的 {} 中,忽略其他所有 {}。例如,如果我们有一个角度类型为锐角的点,我们只会打印出锐角部分。还要注意,由于直角有一个布尔值附加,我们可以使用一个名为 axis_aligned 的变量,该变量被设置为该值的任何值。然后我们可以在 {} 中使用它来打印更多关于角度的信息。注意,我们匹配枚举的所有变体。这是 match 语句的要求。为了说明这一点,我们可以匹配以下函数中的数字
fn print_specific_number_facts(num: u8) {
match num {
0 => println!("The number representing nothingness"),
2 => println!("The only even prime number!"),
6 => println!("A perfect number"),
}
}
首先要注意,我并没有在行上添加 {}。这是因为我们只有一个匹配数字后的单行,所以我们可以省略它们,但我们必须在行尾添加逗号。这将无法编译,因为它不知道如果我们得到一个不是 1、2 或 6 的数字该怎么办。如果我们想要它在接收没有事实的数字时什么也不做,我们可以明确地说
fn print_specific_number_facts(num: u8) {
match num {
0 => println!("The number representing nothingness"),
2 => println!("The only even prime number!"),
6 => println!("A perfect number"),
_ => {},
}
}
下划线充当匹配所有,空 {} 表示我们不想在这种情况下执行任何操作。我们也可以在其他地方使用下划线。还记得上一页的 is_angle_right 函数吗?作为参考,这是它之前的代码
fn is_angle_right(points: Points) -> bool {
points.angle_type == AngleType::Right
}
这不再有效,因为我们可以有 AngleType::Right(true) 或 AngleType::Right(false)。与其分别匹配这两个,我们可以把它改为
fn is_angle_right(points: Points) -> bool {
points.angle_type == AngleType::Right(_)
}
此外,如果我们想要检查只对特定枚举变体执行某些操作并使用内部值(s)。一个方便的方法来描述这种模式是使用 'if let'。
fn print_right_angle(points: Points) {
if let AngleType::Right(axis_aligned) = points.angle_type {
if axis_aligned {
println!("axis aligned right angle");
} else {
println!("non axis aligned right angle");
}
} else {
println!("Some other angle");
}
}
这对描述这种模式非常方便,也很容易阅读。还有许多其他的枚举和结构模式,以及许多与这些模式匹配的方法,但这些是组织和结构化 Rust 中数据的基本构建块。