有趣的Scala模式匹配
Posted 鸿的学习笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有趣的Scala模式匹配相关的知识,希望对你有一定的参考价值。
Scala提供了一种类比switch/case更为强大的选择匹配模式,写作
选择语句 match {可选分支}
它被称为模式匹配,模式匹配包含了一系列以case关键字开头的分支,每一个分支包含一个模式或者是多个表达式。模式有很多种,例如常量模式('*',1),变量模式(可以匹配任何值),通配模式(又见面了,'_'符号),构造方法模式(类似于样例类的初始化)等等。
用一个例子简单说明就是:
scala> def matchTest(expr:Int) = expr match {
| case 1 => println(1)
| case 2 => println(2)
| case _ => println(3)
| }
matchTest: (expr: Int)Unit
scala> matchTest(1)
1
scala> matchTest(2)
2
scala> matchTest(4)
3
match表达式会逐个尝试case里的模式直到匹配为止,如果没有匹配上就会抛出异常MatchError,所以一定要确保case都被覆盖。上例所展示的就是常量模式的常量1,2去匹配,还使用了_通配符匹配任何对象(建议放在最后面,因为Scala的模式匹配是按顺序的)。类似于通配符,为了使用传入的变量,还可以指定变量(当以小写字母开头时,会被认为时变量,然后会被认为是常量),使用变量模式。
scala> def matchTest(expr:Int) = expr match {
| case 0 => println(0)
| case some => println(some)
| }
matchTest: (expr: Int)Unit
scala> matchTest(0)
0
scala> matchTest(3)
3
当然,除了上述的模式,还可以选择构造方法匹配。例如:
scala> case class Test2(a:String)
defined class Test2
scala> case class Test1(name:String, mt:Test2)
defined class Test1
scala> def matchTest(expr:Test1):Test2 = expr match {
| case Test1("a",e)=> e
| case _ => Test2("ab")
| }
matchTest: (expr: Test1)Test2
scala> val a = Test2("cd")
a: Test2 = Test2(cd)
scala> val b = Test1("ab",a)
b: Test1 = Test1(ab,Test2(cd))
scala> matchTest(b)
res0: Test2 = Test2(ab)
scala> val b = Test1("a",a)
b: Test1 = Test1(a,Test2(cd))
scala> matchTest(b)
res1: Test2 = Test2(cd)
我们创造了两个样例类Test1和Test2,Test1接受Test2作为构造参数,实例化两个样例类后发现,在构造方法匹配中,Scala采用了深度匹配,这说明模式匹配不仅仅会检查类是否相等,还会检查对象的内容是否匹配。由构造方法匹配自然而然就可以引申为序列模式匹配和元组匹配。
序列模式匹配
scala> def matchTest(expr:List[String]):Unit = expr match {
| case List("a",_,_)=> println("right")
| case _ => println("wrong")
| }
matchTest: (expr: List[String])Unit
scala> matchTest(List("a"))
wrong
scala> matchTest(List("a","b","c"))
right
可以使用_*来省略后面的多个_符号
元组模式
scala> def matchTest(expr:Any):Unit = expr match {
| case (a,b,c)=> println("found:" +a+b+c)
| case _ => println("wrong")
| }
matchTest: (expr: Any)Unit
scala> matchTest(("a","b","c"))
found:abc
匹配类型的模式
除了上述的匹配模式选出值,还可以用来做类型检查和测试。这里可以根据传进去的值的类型反馈对应的结果。
scala> def matchTest(expr:Any) = expr match {
| case s:String=> s.length
| case i:Int => i
| }
matchTest: (expr: Any)Int
scala> matchTest("abc")
res5: Int = 3
scala> matchTest(2)
res6: Int = 2
以上是关于有趣的Scala模式匹配的主要内容,如果未能解决你的问题,请参考以下文章