1、模式
模式是Rust中的一种特殊语法,用于匹配复杂和简单类型的结构
将模式与匹配表达式和其他构造结合使用,可以更好地控制程序的控制流
模式由以下元素(的一些组合)组成:
―字面值
-解构的数组、enum、struct和 tuple
―变量
―通配符
-占位符
想要使用模式,需要将其与某个值进行比较:
一如果模式匹配,就可以在代码中使用这个值的相应部分
2、用到模式的地方
match的Arm
match表达式的要求;一详尽(包含所有的可能性)
一个特殊的模式:_(下划线):
-它会匹配任何东西
―不会绑定到变量
一通常用于match的最后一个arm;
或用于忽略某些值。
条件if let表达式
if let表达式主要是作为一种简短的方式来等价的代替只有一个匹配项的matchif 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!("1:{}",color);
} else if is_tuesday {
println!("2");
} else if let Ok(age) = age {
if age > 30 {
println!("3:{}",age);
} else {
println!("4:{}",age);
}
} else {
println!("5");
}
}
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 a = 5;
let (x,y,z) = (1,2,3);
// let (q,w) = (1,2,3);
}
函数参数
函数参数也可以是模式
fn foo(x:i32) {
}
fn print_coordinates(&(x,y):&(i32,i32)) {
println!("Current location:({},{})",x,y);
}
fn main() {
let point = (3,5);
print_coordinates(&point);
}
可辩驳性:
模式是否会无法匹配
模式的两种形式
模式有两种形式:可辨驳的、无可辩驳的
能匹配任何可能传递的值的模式:无可辩驳的
一例如:let x = 5;
对某些可能的值,无法进行匹配的模式:可辨驳的
―例如:if let Some(x) = a_value
函数参数、let语句、for循环只接受无可辩驳的模式
if let和l while let接受可辨驳和无可辩驳的模式
fn main() {
let a:Option<i32> = Some(5);
let Some(x) = a;
}
let是无可辩驳的模式
Some是可辩驳的模式
fn main() {
let a:Option<i32> = Some(5);
if let Some(x) = a {
}
}
我们改成if let的模式就可以通过编译了
if let的是可失败的
3、模式语法
匹配字面值
模式可直接匹配字面值
fn main() {
let x = 1;
match x {
1 => println!("1"),
2 => println!("2"),
3 => println!("3"),
_ => println!("anything"),
}
}
匹配命名变量
命名的变量是可匹配任何值的无可辩驳模式
fn main() {
let x = Some(5);
let y = 10;
match x {
Some(5) => println!("5"),
Some(y) => println!("y:{}",y),
_ => println!("{:?}",x),
}
println!("{:?},{:?}",x,y);
}
多重模式
在 match表达式中,使用│语法(就是或的意思),可以匹配多种模式
fn main() {
let x = 1;
match x {
1|2 => println!("one or two"),
3 => println!("three"),
_ => println!("{:?}",x),
}
}
使用..=来匹配某个范围的值
fn main() {
let x = 5;
match x {
1..=5 => println!("one througth five"),
_ => println!("something else"),
}
let x = 'c';
match x {
'a'..='j' => println!("early ASCII Letter"),
'k'..='z' => println!("late ASCII Letter"),
_ => println!("somthing 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);
// let Point {x,y} = p;
// assert_eq!(0,a);
// assert_eq!(7,b);
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 destucture.");
},
Message::Move{x,y} => {
println!("x:{},y:{}",x,y);
},
Message::Write(text) => println!("Text message:{}",text),
Message::ChangeColor(r,g,b) => {
println!("r:{},g:{},b:{}",r,g,b);
},
}
}
解构嵌套的struct和 enum
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!("r:{},g:{},b:{}",r,g,b);
},
Message::ChangeColor(Color::Hsv(r,g,b)) => {
println!("r:{},g:{},b:{}",r,g,b);
},
_=>()
}
}
解构struct和 tuple
struct Point {
x:i32,
y:i32,
}
fn main() {
let ((feet,inches),Point{x,y}) = ((3,10),Point{x:3,y:-10});
}
在模式中忽略值
有几种方式可以模式中忽略整个值或部分值:
_
_配合其它模式
使用以_开头的名称
..(忽略值的剩余部分)
使用_来忽略整个值
fn foo(_:i32,y:i32) {
println!("This y value is :{}",y);
}
fn main() {
foo(3, 4);
}
使用嵌套的_来忽略值的一部分
fn main() {
let mut setting_value = Some(5);
let mut new_setting_value = Some(5);
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);
let numbers = (2,3,4,5,6);
match numbers {
(first,_,thrid,_,fifth) => {
println!("Some numbers:{},{},{}",first,thrid,fifth);
}
}
}
通过使用_开头命名来忽略未使用的变量
fn main() {
// let _x = 5;
// let y = 10;
let s = Some(String::from("Hello!"));
if let Some(_) = s {
println!("found a string");
}
println!("{:?}",s);
}
使用..来忽略值的剩余部分
struct Point {
x:i32,
y:i32,
z:i32
}
fn main() {
let origin = Point{x:0,y:0,z:0};
match origin {
Point{x,..}=>println!("x is {}",x),
}
let numbers = (2,4,6,8,10);
match numbers {
(first,..,last) => {
println!("Some numbers:{},{}",first,last);
}
}
// match numbers {
// (..,second,..) => {
// println!("Some numbers:{}",second);
// }
// }
}
使用match守卫来提供额外的条件
match守卫就是match arm模式后额外的if条件,想要匹配该条件也必须满足
match守卫适用于比单独的模式更复杂的场景
// fn main() {
// let num = Some(4);
// match num {
// Some(x) if x < 5 => println!("less than five:{}",x),
// Some(x)=>println!("{}",x),
// None=>(),
// }
// }
// fn main() {
// let x = Some(5);
// let y = 10;
// match x {
// Some(50) => println!("Got 50"),
// Some(n) if n ==y =>println!("Matched,n={:?}",n),
// _=>println!("Default case,x={:?}",x),
// }
// println!("at the end:x={:?},y={:?}",x,y);
// }
fn main() {
let x = 4;
let y = false;
match x {
4 | 5 | 6 if y => println!("yes"),
_=>println!("no")
}
}
@绑定
@符号让我们可以创建一个变量,该变量可以在测试某个值是否与模式匹配的同时保存该值
enum Message {
Hello{id:i32},
}
fn main() {
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 another range")
}
Message::Hello { id} => {
println!("Found some other id:{}",id)
}
}
}