首先是要构建清单。第三个必须恰好是3就行了,第四个可以是任何东西,之所以将其命名为somethingElse,是因为可以在s插值字符串中重用它。即将就是主题了。这种模式更加灵活,几乎无数个列表可以匹配该模式,而不是我们之前使用的4元素列表模式。它允许案例仅匹配那些符合该类型的模式。当捕获异常时,特别有用。valbobsInfo=bobmatch{casep@Person=>s“$name的信息:${requestMoreInfo}”}答:命名要匹配的模式,以便以后可以重用。另请注意,该条件没有括号。

1.列表提取器
列表可以通过多种功能强大的模式匹配来解构。首先是要构建清单。
val countingList = List(1,2,3,42)
使用类似于案例类构造函数的模式从此列表中提取任何元素:
val mustHaveThree = countingList match {case List(_, _, 3, somethingElse) => s“ 有一个包含3作为第三个元素的列表,之后我发现$ somethingElse”}
此模式将一个列表与四个元素完全匹配,其中我们不关心前两个元素。第三个必须恰好是3就行了,第四个可以是任何东西,之所以将其命名为somethingElse,是因为可以在s插值字符串中重用它。
2. Haskell-Like前置
如果认为清单与以前相同,则可以按照下面的提取清单的开头和结尾:
val startsWithOne = countingList match {case 1 :: someOtherElements => “此列表以一个开头,其余为$ someOtherElements”}
不要问这怎么可能。即将就是主题了。前置模式在处理列表的代码中非常有用,别忘记啦,但是当事先不知道列表是否为空时,可以这样写:
def processList(numbers: List[Int]): String = numbers match {case Nil => ""case h :: t => h" "processList(t)}
熟悉Haskell的人可能非常熟悉这种处理列表的方式。
3.列出Vararg模式
上面显示的第一个模式只能将列表限制为一定数量的元素。如果不知道元素的数量又咋办?
val dontCareAboutTheRest = countingList match {case List(_, 2, _*) => "只关心此列表具有2,作为第二个元素"}
_ _*是重要的位,表示“任何数量的附加参数”。这种模式更加灵活,几乎无数个列表可以匹配该模式,而不是我们之前使用的4元素列表模式。唯一_*要注意的是它必须是模式中的最后一位。换句话说,该情况下,List(_, 2, _*, 55),将无法被翻译。
4.其他列表中缀模式
当我们可以测试列表的开头,甚至测试列表中的元素时,它很有用。但我们要测试列表的最后一个元素呢?
val mustEndWithMeaningOfLife = countingList match {case List(1,2,_) :42 =>}
: 是追加操作符,这很像::从视图模式匹配的点。也可以使用 :prepend运算符,但我更喜欢::
val mustEndWithMeaningOfLife2 = countingList match {case List(1, _*) :42 => }
5.类型说明符
有时,实际上并不关心要匹配的值,而只关心它们的类型。
def gimmeAValue(): Any = { ... }val gimmeTheType = gimmeAValue() match {case _: String =>case _: Int =>case _ => }
该:String位是重要的组成部分。它允许案例仅匹配那些符合该类型的模式。当捕获异常时,特别有用。
try {...} catch {case _: IOException =>case _: Exception =>case _: RuntimeException => }
类型防护的缺点是它们基于反射。别忘记了,这点真的容易犯错。
6.名称绑定
我看过以下模式的次数超出了我的预期:
def requestMoreInfo(p: Person): String = { ... }val bob = Person("Bob", 34, List(“ Inception”,“ The Departed”))val bobsInfo = bob match {case Person(name, age, movies) => s“ $ name的信息:$ {requestMoreInfo(Person(姓名,年龄,电影))}”}
我们解构一个案例类只是为了用相同的数据重新实例化它,以便以后使用。如果不关心case类中的任何字段,但是,如果关心的不是全部和整个实例,又该咋办呢?
val bobsInfo = bob match {case p @ Person(name, _, _) => s“ $ name的信息:$ {requestMoreInfo(p)}”}
答:命名要匹配的模式,以便以后可以重用。甚至可以命名子模式:
val bobsInception = xiaoming match {case Person(name, _, movies @ List("Inception", _*)) => s“ $ name真的很喜欢Inception,其他电影也很喜欢:$ movies”}
7. Conditional Guards
如果像我一样,可能至少尝试过一次模式匹配满足条件的内容,由于只知道“任何”和“恒定”模式,因此放弃了模式匹配,而是使用了链式if-elses,这也是经常的。
val ordinal = gimmeANumber() match {case 1 => "first"case 2 => "second"case 3 => "third"case n if n % 10 == 1 => n"st"case n if n % 10 == 2 => n"nd"case n if n % 10 == 3 => n"rd"case n => n"th"}
如上所示,if防护直接位于模式中。另请注意,该条件没有括号。
8.替代模式
如果针对多个模式返回相同的表达式,则无需c v去复制相同的代码。
val myOptimalList = numbers match {case List(1, _, _) => “我喜欢这个列表”case List(43, _*) => “我喜欢这个列表”case _ => “我不喜欢这个列表”}
也可以将返回相同表达式的模式组合为一个模式:
val myOptimalList = numbers match {case List(1, _, _) | List (43, _*) => “我喜欢这个列表”case _ => “我不喜欢这个列表”}
这种模式的唯一缺点是不能绑定任何名称,因为无法确保这些值在右侧可用。
在许多情况下,例如,想处理多种异常时,此模式在实践中很有用:
try {...} catch {case _: RuntimeException | _: IOException => ""}
最后,没什么好说的,大家今天都过得愉快吧。
