文章目录
- 模式和匹配
-
- [match 分支](#match 分支)
- [if let表达式](#if let表达式)
- [while let](#while let)
- [for 循环](#for 循环)
- [let 语句](#let 语句)
- 函数参数
- Refutability(可失败)与Irrefutable(不可失败的)
- 模式语法
- 解构并分解值
-
- 解构结构体
- 解构枚举
- 解构结构体和元组
- 忽略模式中的值
- [使用 _ 忽略整个值](#使用 _ 忽略整个值)
- [使用嵌套的 _ 忽略部分值](#使用嵌套的 _ 忽略部分值)
- 通过在名字前以一个下划线开头来忽略未使用的变量
- [用 .. 忽略剩余值](#用 .. 忽略剩余值)
- 匹配守卫提供的额外条件
- [@ 绑定](#@ 绑定)
- 参考
模式和匹配
match 分支
所有结果都得匹配到
rust
// Match Expression
fn main() {
#[derive(Debug)]
enum Language {
English,
Spanish,
Russian,
Japanese,
}
let language = Language::English;
match language {
Language::English => println!("Hello World!"),
Language::Spanish => println!("Hola Mundo!"),
Language::Russian => println!("npuBeT, Mnp!"),
//_=> println!("Unsupported language!"),
lang => println!("Unsupported language! {:?}", lang),
}
}
if let表达式
if let表达式缺点:编译期无法强制保证覆盖所有的情况
rust
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
rust
#![allow(unused)]
fn main() {
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
// 一旦其返回 None,while 循环停止。
while let Some(top) = stack.pop() {
println!("{}", top);
}
}
for 循环
rust
#![allow(unused)]
fn main() {
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
println!("{} is at index {}", value, index);
}
}
let 语句
rust
#![allow(unused)]
fn main() {
let x = 5;
// 将指分别绑定到x, y和z上
let (x, y, z) = (1, 2, 3);
let (x, y, _) = (1, 2, 3);
}
函数参数
rust
//一个在参数中解构元组的函数
fn print_coordinates(&(x, y): &(i32, i32)) {
println!("Current location: ({}, {})", x, y);
}
fn main() {
let point = (3, 5);
print_coordinates(&point);
}
Refutability(可失败)与Irrefutable(不可失败的)
rust
fn main() {
// Irrefutable(不可失败的)
let x = 5;
// Refutable(可失败的),如果x是None,模式则无法匹配
let x: Option<&str> = None;
if let Some(x) = x {
println!("{}", x)
}
// 只能接受不可失败模式
//function parameters
// let statements
// for loops
// 既可以接受可失败,也可以接受不可失败
// if let
// while let
}
rust
fn main() {
let x: Option<&str> = None;
let Some(x) = x; //error:`let` bindings require an "irrefutable pattern"
//error:这个模式总是匹配,所以这个 `if` 没啥用
if let x = 5 {
println!("{}", x);
};
}
模式语法
匹配字面量
rust
fn main() {
let x = 1;
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("anything"),
}
}
匹配命名变量
rust
fn main() {
let x = Some(5);
let y = 10;
match x {
Some(50) => println!("Got 50"),
Some(y) => println!("Matched, y = {:?}", y),//因为定义了y,会遮蔽外面的y
_ => println!("Default case, x = {:?}", x),
}
println!("at the end: x = {:?}, y = {:?}", x, y);
}
多个模式
rust
#![allow(unused)]
fn main() {
let x = 1;
match x {
1 | 2 => println!("one or two"),
3 => println!("three"),
_ => println!("anything"),
}
}
通过 ...= 匹配值的范围
只适用于数值和字符
rust
#![allow(unused)]
fn main() {
let x = 5;
match x {
1..=5 => println!("one through five"),
_ => println!("something else"),
}
let x = 'c';
match x {
'a'..='j' => println!("early ASCII letter"),
'k'..='z' => println!("late ASCII letter"),
_ => println!("something else"),
}
}
解构并分解值
解构结构体
rust
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);
}
可以简写如下:
rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 0, y: 7 };
let Point { x, y } = p;
assert_eq!(0, x);
assert_eq!(7, y);
}
使用字面量作为结构体模式的一部分进行解构
rust
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),
}
}
解构枚举
rust
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
)
}
}
}
解构嵌套的结构体和枚举
rust
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
)
}
_ => (),
}
}
解构结构体和元组
rust
#![allow(unused)]
fn main() {
struct Point {
x: i32,
y: i32,
}
let ((feet, inches), Point {x, y}) = ((3, 10), Point { x: 3, y: -10 });
}
忽略模式中的值
使用 _ 忽略整个值
rust
fn foo(_: i32, y: i32) {
println!("This code only uses the y parameter: {}", y);
}
fn main() {
foo(3, 4);
}
使用嵌套的 _ 忽略部分值
rust
#![allow(unused)]
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);
}
rust
let numbers = (2, 4, 8, 16, 32);
match numbers {
(first, _, third, _, fifth) => {
println!("Some numbers: {}, {}, {}", first, third, fifth)
},
}
通过在名字前以一个下划线开头来忽略未使用的变量
给变量增加下划线前缀和使用_是不同的
rust
fn main() {
let _x = 5;
let y = 10;
}
rust
#![allow(unused)]
fn main() {
let s = Some(String::from("Hello!"));
//s中的值会被移入到_s中,虽然你用了忽略
if let Some(_s) = s {
println!("found a string");
}
println!("{:?}", s);
}
解决办法
rust
#![allow(unused)]
fn main() {
let s = Some(String::from("Hello!"));
// 然而只使用下划线本身,并不会绑定值。
if let Some(_) = s {
println!("found a string");
}
println!("{:?}", s);
}
用 ... 忽略剩余值
rust
#![allow(unused)]
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),
}
}
... 会扩展为所需要的值的数量
rust
fn main() {
let numbers = (2, 4, 8, 16, 32);
match numbers {
(first, .., last) => {
println!("Some numbers: {}, {}", first, last);
}
}
}
匹配守卫提供的额外条件
rust
#![allow(unused)]
fn main() {
let num = Some(4);
match num {
Some(x) if x < 5 => println!("less than five: {}", x),
Some(x) => println!("{}", x),
None => (),
}
}
rust
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),//个 y 正是 外部的 y
_ => println!("Default case, x = {:?}", x),
}
println!("at the end: x = {:?}, y = {}", x, y);
}
rust
#![allow(unused)]
fn main() {
let x = 4;
let y = false;
match x {
4 | 5 | 6 if y => println!("yes"),//且
_ => println!("no"),
}
}
@ 绑定
rust
#![allow(unused)]
fn main() {
enum Message {
Hello { id: i32 },
}
let msg = Message::Hello { id: 5 };
match msg {
// Message::Hello 的 id 字段是否位于 3..=7 范围内,同时也希望能将其值绑定到 id_variable 变量中以便此分支相关联的代码可以使用它。可以将 id_variable 命名为 id
Message::Hello {
id: id_variable @ 3..=7,
} => {
println!("Found an id in range: {}", id_variable)
}
// 没有将 id 值保存进一个变量。
Message::Hello { id: 10..=12 } => {
println!("Found an id in another range")
}
Message::Hello { id } => {
println!("Found some other id: {}", id)
}
}
}