模式
模式是Rust中特殊的语法,用来匹配值的结构
组成:
(1) 字面值
(2) 解构的数组、枚举、结构体或者元组
(3) 变量
(4) 通配符
(5) 占位符
match的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 fn main () { let a = 1 ; match a { 0 => println! ("Zero" ), 1 => println! ("One" ), _ => println! ("other value" ), }; }
if let
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 fn main () { let color : Option <&str > = None ; let is_ok = true ; let age : Result <u8 ,_> = "33" .parse (); if let Some (c) = color { println! ("color = {}" ,c); } else if is_ok { println! ("is ok" ); }else if let Ok (a) = age { if a > 30 { println! ("oh,mature man" ); }else { println! ("oh,young man" ); } }else { println! ("is else" ); } }
while let
1 2 3 4 5 6 7 8 9 10 11 fn main () { let mut stack = Vec ::new (); stack.push (1 ); stack.push (2 ); stack.push (3 ); while let Some (top) = stack.pop () { println! ("top = {}" ,top); } }
for
在for循环中模式是直接跟随for循环字
此处的模式是(index,value)
1 2 3 4 5 6 fn main () { let v = vec! ['a' ,'b' ,'c' ]; for (index,value) in v.iter ().enumerate () { println! ("index: {},value {}" ,index,value); } }
let语句
1 2 3 4 5 6 7 8 fn main () { let (x,y,z) = (1 ,2 ,3 ); println! ("{},{},{}" ,x,y,z); let (x,..,z) = (1 ,2 ,3 ); println! ("{},{}" ,x,z); }
函数的模式
1 2 3 4 5 6 7 8 9 fn print_point (&(x,y): &(i32 ,i32 )) { println! ("x = {},y = {}" ,x,y); } fn main () { let p = (3 ,5 ); print_point (&p); }
模式的可反驳和不可反驳
模式有两种:refutable 和irrefutable(可反驳的和不可反驳的),能够匹配任何传递的可能值
的模式叫做不可反驳模式,对值匹配可能失败的叫做可反驳模式
只能接受不可反驳模式的由: 函数、let语句、for循环,因为其通过不匹配的值程序无法进行有意义工作
if let和while let表达式被限制为只能接受可反驳的模式,因为他们定义就是为了处理有可能失败的条件
1 2 3 4 5 6 7 8 9 10 fn main () { let a : Option <i32 > = Some (5 ); let b : Option <i32 > = None ; if let Some (v) = a { println! ("v = {}" ,v); } }
匹配字面值
1 2 3 4 5 6 7 8 fn main () { let x = 1 ; match x { 1 => println! ("one" ), 2 => println! ("two" ), - => println! ("xx" ), }; }
匹配命名变量
1 2 3 4 5 6 7 8 9 10 11 fn main () { let x = Some (5 ); let y = 10 ; match x { Some (50 ) => println! ("50" ), Some (y) => println! ("y = {}" ,y), _ => println! ("other" ), }; println! ("x = {:?},y = {:?}" ,x,y); }
多个模式
1 2 3 4 5 6 7 8 fn main () { let x = 1 ; match x { 1 |2 => println! ("1 or 2" ), 3 => println! ("3" ), - => println! ("xx" ), }; }
通过…匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fn main () { let x = 5 ; match x { 1 ..=5 => println! ("1 to 5" ), - => println! ("xx" ), }; let x = 'c' ; match x { 'a' ..='j' => println! ("1" ), 'k' ..='z' => println! ("2" ), _ => println! ("other" ), }; }
解构并分解值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 struct Point { x: i32 , y: i32 , } fn main () { let p = Point {x: 1 ,y: 2 }; let Point {x:a,y:b} = p; let Point {x:x,y:y} = p; assert_eq! (1 ,x); assert_eq! (1 ,y); assert_eq! (1 ,a); assert_eq! (2 ,b); }
1 2 3 4 5 6 7 let p = Point {x:1 ,y:0 };match p { Point {x=0 ,y=0 } => println! ("原点" ), Point {x,y:0 } => println! ("x axis" ), Point{x=0 ,y} => println! ("y axis" ), Point {x,y} => println! ("other" ), };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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! ("quit" ); }, Message::Move{x,y} => {println! ("move x {} y {}" ,x,y);}, Message::Write (text) => println! ("write msg = {}" ,text), Message::ChangeColor (r,g,b) => { println! ("color, r = {},g = {},b= {}" ,r,g,b); }, }; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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! ("rgb color, r = {},g= {},b = {}" ,r,g,b); }, Message::ChangeColor (Color::Rgb (r,g,b)) => { println! ("hsv color, h = {},s= {},v = {}" ,h,s,v); }, _ => () }; }
1 2 3 4 5 6 7 8 9 struct Point { x: i32 , y: i32 , } fn main () { let ((a,b),Point{x,y}) = ((1 ,2 ),Point{x: 3 ,y: 4 }); }
忽略模式中的值
可能使用下划线的场景
1 2 3 4 5 6 7 8 9 10 11 trait A { fn bar (x :i32 ,y: i32 ); } struct B { } impl A for B { fn bar (_ :i32 ,y: i32 ) { println! ("y = {}" ,y); } }
1 2 3 4 5 6 7 fn foo (_ : i32 ,y: i32 ) { println! ("y = {}" ,y); } fn main () { foo (1 ,2 ); }
1 2 3 4 5 6 7 8 fn main () { let numbers = (1 ,2 ,3 ,4 ); match numbers { (one,_,three,_) => { println! ("one {},three {}" ,one,three); }, } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 fn main () { let _x = 5 ; let _y = 5 ; let s = Some (String ::from ("hello" )); if let Some (_c) = s { println! ("found a string" ); } let s = Some (String ::from ("hello" )); if let Some (_) = s { println! ("found a string" ); } println! ("s = {}" ,s); }
使用…匹配的过程中一定不能出现歧义
如错误例子:
1 2 3 4 5 match numbers { (..,seconds,..) => { println! ("second = {}" ,second); } }
1 2 3 4 5 6 7 8 fn main () { let numbers = (1 ,2 ,3 ,4 ,5 ,6 ,7 ); match numbers { (first,..,last) => { println! ("first {},last {}" ,first,last); }, }; }
匹配守卫提供额外的条件
匹配守卫是一个指定于match分支模式之后,如果想要使用额外的if条件,必须满足这个分支
这种方法不需要引进新的变量
1 2 3 4 5 6 7 8 fn main () { let num = Some (4 ); match num { Some (x) if x < 5 => println! ("<5" ), Some (x) => println! ("x {}" ,x), None => (), }; }
1 2 3 4 5 6 7 8 9 fn main () { let num = Some (4 ); let y = 10 ; match num { Some (x) if x == y => println! ("num ==y" ), Some (x) => println! ("x {}" ,x), None => (), }; }
1 2 3 4 5 6 7 8 fn main () { let x = 4 ; let y = false ; match x { 4 |5 |6 if y => println! ("1" ), _ => println! ("2" ), }; }
使用@运算符