模式
- 模式是RUST中的一种特殊语法,用于匹配复杂和简单类型的结构
- 将模式与匹配表达式和其他构造结合使用,可以更好地控制程序的控制流
- 模式同以下元素(的一些组合)组成:
- 字面值
- 解构的数组、enum、struct 和 tuple
- 变量
- 通配符
- 占位符
- 想要使用模式,需要将其与某个值进行比较
能用到模式的地方
- match的Arm
match VALUE { PATTERN => EXPRESSION, PATTERN => EXPRESSION, PATTERN => EXPRESSION, }
- match表达式的要求:
- 详尽(包含所有的可能性)
- 一个特殊的模式:_(下划线):
- 它会匹配任何东西
- 不会绑定到变量
- 能常用于match的最后一个arm;或用于忽略某些值
条件 if let表达式
- if let表态式主要是作为一种简短的方式来等价的代替只有一个匹配项的match
- if let可选的可以拥有else,包括:
- else if
- else if let
- 但,if let 不会检查穷尽性
fn main() {
let favorite_color: Option<&str> = None;
let is_tuesday = false;
let age: Result<u8, _> = "34".parse();
if let Some(color) = favorite_color {
println!("Using your favorite color, {}, as the background", color);
} else if is_tuesday {
println!("Tuesday is green day!");
} else if let Ok(age) = age {
if age > 30 {
println!("Using purple as the background color");
} else {
println!("Using orange as the background color");
}
} else {
println!("Using blue as the background color");
}
}
while let条件循环
- 只要模式继续满足匹配的条件,那它允许while循环一直运行
fn main() {
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
println!("{}", top);
}
}
for循环
- for 循环是Rust中最常见的循环
- for 循环中,模式就是紧随for关键字后的值
fn main() {
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
println!("{} is at index {}", value, index);
}
}
let 语句
- let 语句也是模式
- let PATTERN = EXPRESSION
fn main() {
let (x, y, z) = (1, 2, 3);
}
函数参数
- 函数参数也可以是模式
fn print_coordinates(&(x, y): &(i32, i32)) {
println!("Current location: ({}, {})", x, y);
}
fn main() {
let point = (3, 5);
print_coordinates(&point);
}
可辩驳性:模式是否会无法匹配
- 模式的两种形式
- 模式有两种形式: 可辩驳的,无可辩驳的
- 能匹配任何可能传递的值的模式:无可辩驳的
- 对某些可能的值,无法进行匹配的模式:可辩驳的
- 例如: if let some(x) = a_value
- 函数参数、let语句、for循环只接受无可辩驳的模式
模式语法
- 匹配字面值
fn main() {
let x = 1;
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("anything"),
}
}
- 匹配命名变量
- 命名的变量是可匹配任何值的无可辩驳模式
fn main() { let x = Some(5); let y = 10; match x { Some(50) => println!("Got 50"), Some(y) => println!("Matched, y = {:?}", y), _ => println!("Default case, x = {:?}", x), } println!("at the end: x = {:?}, y = {:?}", x, y); }
- 多重模式
- 在match表达试中,使用|语法(就是或的意思),可以匹配多种模式
fn main() { let x = 1; match x { 1 | 2 => println!("one or two"), 3 => println!("three"), _ => println!("anything"), } }
- 使用 ..=来匹配某个范围的值
fn main() {
let x = 'c';
match x {
'a'..='j' => println!("early ASCII letter"),
'k'..='z' => println!("late ASCII letter"),
_ => println!("something else"),
}
}
- 解构以分解值
- 可以使用模式来解构struct、enum、tuple,从而引用这些类型值的不同部分
struct Point { x: i32, y: i32, } fn main() { let p = Point { x: 0, y: 7 }; let Point { x: a, y: b } = p; assert_eq!(0, a); assert_eq!(7, b); } struct Point { x: i32, y: i32, } fn main() { let p = Point { x: 0, y: 7 }; match p { Point { x, y: 0 } => println!("On the x axis at {}", x), Point { x: 0, y } => println!("On the y axis at {}", y), Point { x, y } => println!("On neither axis: ({}, {})", x, y), } }
- 解构enum
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } fn main() { let msg = Message::ChangeColor(0, 160, 255); match msg { Message::Quit => { println!("The Quit variant has no data to destructure.") } Message::Move { x, y } => { println!( "Move in the x direction {} and in the y direction {}", x, y ); } Message::Write(text) => println!("Text message: {}", text), Message::ChangeColor(r, g, b) => println!( "Change the color to red {}, green {}, and blue {}", r, g, b ), } } enum Color { Rgb(i32, i32, i32), Hsv(i32, i32, i32), } enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(Color), } fn main() { let msg = Message::ChangeColor(Color::Hsv(0, 160, 255)); match msg { Message::ChangeColor(Color::Rgb(r, g, b)) => println!( "Change the color to red {}, green {}, and blue {}", r, g, b ), Message::ChangeColor(Color::Hsv(h, s, v)) => println!( "Change the color to hue {}, saturation {}, and value {}", h, s, v ), _ => (), } }
- 解构struct和tuple
fn foo(_: i32, y: i32) { println!("This code only uses the y parameter: {}", y); } fn main() { foo(3, 4); }
- 在模式中忽略值
- 有几种方式可以模式中忽略整个值或部分值:
- _
fn foo(_: i32, y: i32) { println!("This code only uses the y parameter: {}", y); } fn main() { foo(3, 4); }
- _配合其它模式
fn main() { let mut setting_value = Some(5); let new_setting_value = Some(10); match (setting_value, new_setting_value) { (Some(_), Some(_)) => { println!("Can't overwrite an existing customized value"); } _ => { setting_value = new_setting_value; } } println!("setting is {:?}", setting_value); }
- 使用以_开头的名称
fn main() { let s = Some(String::from("Hello!")); if let Some(_) = s { println!("found a string"); } println!("{:?}", s); }
- .. (忽略值的剩余部分)
fn main() { struct Point { x: i32, y: i32, z: i32, } let origin = Point { x: 0, y: 0, z: 0 }; match origin { Point { x, .. } => println!("x is {}", x), } }
- 使用match守卫来提供额外的条件
- match守卫主是match arm模式后额外的if条件,想要匹配条件也必须满足
- match守卫适用于比单独的模式更复杂的场景
fn main() { let num = Some(4); match num { Some(x) if x % 2 == 0 => println!("The number {} is even", x), Some(x) => println!("The number {} is odd", x), None => (), } }
@ 绑定
- @符号让我们可以创建一个变量,该变量可以在测试某个值是否与模式匹配的同时保存该值
fn main() {
enum Message {
Hello { id: i32 },
}
let msg = Message::Hello { id: 5 };
match msg {
Message::Hello {
id: id_variable @ 3..=7,
} => println!("Found an id in range: {}", id_variable),
Message::Hello { id: 10..=12 } => {
println!("Found an id in another range")
}
Message::Hello { id } => println!("Found some other id: {}", id),
}
}