当前位置: 首页 > 科技观察

匹配的语法是什么?PHP8也加入了_1113

时间:2023-03-20 14:36:36 科技观察

大家好,我是站长polarisxu。这是Rust退出系列的第8篇教程,探索Rust中的模式匹配。01matchexpression关于matchexpression,其他很多语言都没有,比如Go语言。不过有些语言开始支持match了,比如PHP8.0有了match表达式。一般可以认为match类似于switch,所以Rust中没有switch。match用于检查当前值是否与一组/列值中的一个匹配。看一个具体的例子:fntest_match(number:i32)->&'staticstr{matchnumber{//匹配单个值1=>{println!("One!");"One!"},//匹配多个值2|3|5|7|11=>"Thisisaprime",//匹配一个闭区间范围13..=19=>"Ateen",//处理其他情况_=>"Ain'tspecial",}}see好像是一个简单的语法结构,但在其他语言中大概是看不到的。简单说明:类似于其他语言的switch,可以匹配多个分支;多个分支之间,使用,分开;在match分支中,=>左边是一个模式,所以称为模式匹配,如|表示匹配多个Value;..=表示匹配一个范围;右边是左边匹配成功时要执行的操作;match要求穷尽,即包括所有可能的值。因此,提供_来处理所有其他情况,类似于switch的默认分支;但只要用完了,就不需要_;如果右边的操作是多语句,需要放在{}中;match是一个表达式,它的结果是匹配模式中执行操作的最后一个表达式的结果。这在Rust中很常见,正如前面所说,Rust中的一切都是表达式。所以,这个例子中匹配表达式的值就是函数的返回值。因此,match的所有分支必须返回相同的数据类型;注意匹配表达式末尾是否有分号的区别;日常抱怨:match中的matchintervals,如果想和forin一样,用..表示half-closed和half-openintervals,结果报错。我看到资料应该用...,但它提醒我语法已过时!为什么语法结构不一致?!看一个接收匹配结果的例子:letboolean=true;letbinary=matchboolean{false=>0,true=>1,};//注意这里的分号println!("{}->{}",boolean,二进制);02match的其他用途上面介绍了常规的match操作。火柴还有许多其他用途。当元组和匹配一起使用时,可以解构元组。fnmain(){//尝试给`pair`赋不同的值letpair=(0,-2);println!("Tellmeabout{:?}",pair);//match可以解构一个元组matchpair{//解构第二个值(0,y)=>println!("Firstis`0`and`y`is`{:?}`",y),(x,0)=>println!("`x`is`{:?}`andlastis`0`",x),_=>println!("Itdon'tmatterwhattheyare"),//`_`表示不将值绑定到变量}}关于enum的引用和指针、引用和匹配的组合,后面会解释。guard语句可以在匹配分支中添加过滤条件。按照上面元组解构的例子:fnmain(){letpair=(2,-2);println!("Tellmeabout{:?}",pair);matchpair{(x,y)ifx==y=>println!("Thesearetwins"),//`if`条件部分是一个保护语句(x,y)ifx+y==0=>println!("Antimatter,kaboom!"),(x,_)ifx%2==1=>println!("Thefirstonesodd"),_=>println!("Nocorrelation..."),}}绑定什么意思?看一个例子:(来自rustbyexample)//`age`返回`u32`值的函数。fnage()->u32{15}fnmain(){println!("Tellmetypeofpersonyouare");matchage(){0=>println!("I'mnotbornyetIguess"),//可以直接`match`1..=12、但是如何打印出年龄?//将匹配值绑定到1..=12分支中的`n`。现在可以读取年龄。n@1..=12=>println!("我是machildofage{:?}",n),n@13..=19=>println!("我是mateenofage{:?}",n),//不符合上面的范围。返回结果。n=>println!("I'manoldpersonofage{:?}",n),}}match后面是一个函数,我们希望根据匹配结果在分支中使用age函数的返回值。当然,这个例子有点画蛇添足,完全可以用变量来存储匹配前age函数的返回值。然后换一个例子:fnsome_number()->Option{Some(41)}fnmain(){matchsome_number(){Some(n@40..=42)=>println!("TheAnswer:{}!",n),Some(n)=>println!("Notinteresting...{}",n),_=>(),}}关于Option这个例子以后会很好的解释绑定的作用:branch如果要使用匹配结果,可以通过@符号将匹配结果绑定到一个变量,然后就可以使用这个变量了。03iflet和whilelet这两种结构在其他语言中从未见过。可以理解为在某些场景下替代match,让代码更简洁,因为match必须穷尽所有情况,而iflet和whilelet则没有这个限制。下面的代码:letsome_u8_value=Some(3u8);matchsome_u8_value{Some(3)=>println!("three"),_=>(),//有点多余}改为iflet:letsome_u8_value=Some(3u8);ifletSome(3)=some_u8_value{println!("three");}同match,如果let和whilelet都是表达式;if/whilelet等号左边是模式,右边是要匹配的值;所以当右边的值和左边的模式匹配时,对应的语句块被执行;因此,有时iflet也可以简单地用作解构;iflet支持普通的elseif和else;而let没有别的;whilelet语法类似于iflet。这里没有例子。04小结虽然Rust中的match类似于其他语言中的switch,但是很明显match比switch更复杂。当然,不管复杂与否,最重要的还是要用到实际,需要不断的实践练习。match通常和Option、enumeration一起使用,所以在讲解这两个知识点的时候,一般都会用到match。本文转载自微信公众号「polarisxu」,可通过以下二维码关注。转载本文请联系polarisxu公众号。