Rust学习笔记(五十四)模式(匹配)语法

Rust学习笔记(五十四)模式(匹配)语法

首页游戏大全RustRed更新时间:2024-10-25
匹配字面值

模式匹配可以直接匹配字面值,例:

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),//Some(y)匹配的是x,即Some(5),所以此处y是5 _ => println!("Default case, x = {:?}", x), } println!("at the end: x = {:?}, y = {:?}", x, y); }

运行输出:

Matched, y = 5 at the end: x = Some(5), y = 10

因为模式匹配里的y在模式匹配后已走出作用域,后面打印的y是外面的y。

多重匹配

在match表达式中,使用|(或)语法,可以匹配多种模式,例:

fn main() { let x = 1; match x { 1 | 2 => println!("one or two"), 3 => println!("three"), _ => println!("anything"), } let x = Some(5); match x { Some(1 | 2 | 5) => println!("here"), _ => println!("la la la"), } } 使用..=来匹配某个范围的值

例:

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"), } } 解构以分解值

可以使用模式来解构结构体、枚举、元组,从而引用这些类型值的不同部分。例:

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, x); assert_eq!(7, y); match p { Point { x, y: 0 } => println!("On the x axis at {}", x),//匹配x随意,y是0的情况 Point { x: 0, y } => println!("On the y axis at {}", y),//匹配y随意,x是0的情况 Point { x, y } => println!("On neither axis: ({}, {})", x, y),//匹配x随意,y也随意的情况 } } 解构枚举

例:

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 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 code only uses the y parameter: {}", y); } fn main() { foo(3, 4); }

大部分情况当你不再需要特定函数参数时,最好修改签名不再包含无用的参数。在一些情况下忽略函数参数会变得特别有用,比如实现 trait 时,当你需要特定类型签名但是函数实现并不需要某个参数时。此时编译器就不会警告说存在未使用的函数参数,就跟使用命名参数一样。

fn main() { //_忽略部分 let mut setting_value = Some(5); let new_setting_value = Some(10); match (setting_value, new_setting_value) { (Some(_), Some(_)) => { //只要求setting_value和new_setting_value都是Some即可,忽略里面的值 println!("Can't overwrite an existing customized value"); } _ => { setting_value = new_setting_value; } } println!("setting is {:?}", setting_value); let numbers = (2, 4, 8, 16, 32); match numbers { (first, _, third, _, fifth) => { println!("Some numbers: {}, {}, {}", first, third, fifth) } } }

fn main() { let _x = 5;//_开头会忽略未使用的变量 let y = 10;//没有_,并且未使用的变量会被编译器警告 }

注意, 只使用 _ 和使用以下划线开头的名称有些微妙的不同:比如 _x 仍会将值绑定到变量,而 _ 则完全不会绑定。

fn main() { let s = Some(String::from("Hello!")); if let Some(_s) = s { println!("found a string"); } println!("{:?}", s);//编译器报错,因为_变量仍然会被绑定值,所以 s 的值会移动进 _s,这时s无法使用了。 }

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 }; //使用..忽略x以外的字段 match origin { Point { x, .. } => println!("x is {}", x), } }

fn main() { let numbers = (2, 4, 8, 16, 32); match numbers {//忽略中间的部分(无论中间有多少个),只要第一个和最后一个 (first, .., last) => { println!("Some numbers: {}, {}", first, last); } } }

fn main() { let numbers = (2, 4, 8, 16, 32); match numbers {//存在歧义,因为编译器不知道我们要的是中间的哪一个元素,所以无法编译 (.., second, ..) => { println!("Some numbers: {}", second) }, } } 使用match守卫来提供额外的条件

match守卫就是match分支后额外的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 => (), } let x = 4; let y = false; match x {//配合多重匹配 4 | 5 | 6 if y => println!("yes"), _ => println!("no"), } } @绑定

@符号让我们可以创建一个变量,该变量可以在测试某个值是否与模式匹配的同时保存该值。 例:

fn main() { enum Message { Hello { id: i32 }, } let msg = Message::Hello { id: 5 }; match msg { Message::Hello { id: id_variable @ 3..=7,//要求id的值在3到7的范围时,将其值保存在id_variable中 } => { 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) } } }

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved