第十二章 Scala进阶——模式匹配

本文详细探讨了Scala中的模式匹配,包括样例类与样例对象的特性,如自动工厂方法、参数绑定等。接着,文章介绍了模式匹配的概念和语法,通过常量模式、变量模式、构造方法模式等多个例子展示了模式匹配的使用。同时,文章还讨论了模式匹配的其他方面,如模式守卫、密封类、可选值和偏函数的应用。模式匹配在Chisel硬件描述语言中有着重要应用,为软硬件编程提供了强大的功能。
摘要由CSDN通过智能技术生成

前一章提到过,Scala的内建控制结构里有一个match表达式,用于模式匹配或偏函数。模式匹配是Scala中一个强大的高级功能,并且在Chisel中被用于硬件的参数化配置,可以快速地裁剪、配置不同规模的硬件电路。所以,尽管模式匹配不是很容易就能掌握并熟练运用,但是学会它将会对软、硬件编程都大有帮助。

一、样例类与样例对象

定义类时,若在最前面加上关键字“case”,那么这个类就被称为样例类。Scala的编译器会自动对样例类添加一些语法便利:①添加一个与类同名的工厂方法。也就是说,可以通过“类名(参数)”来构造对象,而不需要“new 类名(参数)”,使得代码看起来更加自然。②参数列表的每个参数都隐式地获得了一个val前缀。也就是说,类内部会自动添加与参数同名的公有字段。③会自动以“自然”的方式实现toString、hashCode和equals方法。④添加一个copy方法,用于构造与旧对象只有某些字段不同的新对象,只需通过传入具名参数和缺省参数实现。比如objectA.copy(arg0 = 10)会创建一个只有arg0为10、其余成员与objectA完全一样的新对象。

一个样例类定义如下:

scala> case class Students(name: String, score: Int)
defined class Students

scala> val stu1 = Students("Alice", 100)
stu1: Students = Students(Alice,100)

scala> stu1.name
res0: String = Alice

scala> stu1.score
res1: Int = 100

scala> val stu2 = stu1.copy()
stu2: Students = Students(Alice,100)

scala> stu2 == stu1
res2: Boolean = true

scala> val stu3 = stu1.copy(name = "Bob")
stu3: Students = Students(Bob,100)

scala> stu3 == stu1
res3: Boolean = false

样例类最大的好处是支持模式匹配。相关内容会在本章接下来的内容中介绍。

样例对象与样例类很像,也是定义单例对象时在最前面加上关键字“case”。尽管样例对象和普通的单例对象一样,没有参数和构造方法,也是一个具体的实例,但是样例对象的实际形式更接近样例类。前面说的样例类的特性,样例对象也具备,例如可用于模式匹配。从编译后的结果来比较,样例对象与一个无参、无构造方法的样例类是一样的。

二、模式匹配

模式匹配的语法如下:

选择器 match { 可选分支 }

其中,选择器就是待匹配的对象,花括号里是一系列以关键字“case”开头的“可选分支”。每个可选分支都包括一个模式以及一个或多个表达式,如果模式匹配成功,就执行相应的表达式,最后返回结果。可选分支定义如下: 

case 模式 => 表达式

match表达式与Java的switch语法很像,但模式匹配功能更多。两者有三个主要区别:①match是一个表达式,它可以返回一个值。②可选分支存在优先级,其匹配顺序也就是代码编写时的顺序,并且只有第一个匹配成功的模式会被选中,然后对它的表达式求值并返回。如果表达式有多个,则按顺序执行直到下个case语句为止,并不会贯穿执行到末尾的case语句,所以多个表达式也可以不用花括号包起来。③要确保至少有一个模式匹配成功,否则会抛出MatchError异常。 

三、模式的种类

模式匹配之所以强大,原因之一就是支持多种多样的模式。

   Ⅰ、通配模式

通配模式用下划线“_”表示,它会匹配任何对象,通常放在末尾用于缺省、捕获所有可选路径,相当于switch的default。如果某个模式需要忽略局部特性,也可以用下划线代替。例如:

scala> def test(x: Any) = x match {
         |     case List(1, 2, _) => true
         |     case _ => false
         |  }
test: (x: Any)Boolean

scala> test(List(1, 2, 3))
res0: Boolean = true

scala> test(List(1, 2, 10))
res1: Boolean = true

scala> test(List(1, 2))
res2: Boolean = false

上述例子中,第一个case就是用下划线忽略了模式的局部特性:表明只有含有三个元素,且前两个为1和2、第三个元素任意的列表才能匹配该模式。不符合第一个case的对象,都会被通配模式捕获。

越具体的模式,可匹配的范围就越小;反之,越模糊的模式,覆盖的范围越大。具体的模式,应该定义在模糊的模式前面,否则如果具体模式的作用范围是模糊模式的子集,那写在后面的具体模式就永远不会被执行。像通配模式这种全覆盖的模式,一定要写在最后。

   Ⅱ、常量模式

常量模式,顾名思义,就是用一个常量作为模式,使得只能匹配常量自己。任何字面量都可以作为常量模式,任何val类型的变量或单例对象(样例对象也是一样的)也可以作为常量模式。例如,Nil这个单例对象能且仅能匹配空列表:

scala> def test2(x: Any) = x match {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值