Scala 程序很多地方都可以使用模式,而不僅僅用在模式匹配( match 表達(dá)式),本篇給出幾種使用模式的情況。
任何時(shí)候你使用 val 或 var 定義變量時(shí),你都可以使用模式定義多個(gè)變量,此時(shí)你定義元組,分別賦值到不同的變量。
scala> val myTuple=(134,"abc")
myTuple: (Int, String) = (134,abc)
scala> var(number,string)= myTuple
number: Int = 134
string: String = abc
這個(gè)情況也適應(yīng) Case classes。 如果你知道某個(gè)值的具體形式,你可以利用模式來分解單個(gè)項(xiàng):
scala> val exp=new BinOp("*",Number(5),Number(1))
exp: BinOp = BinOp(*,Number(5.0),Number(1.0))
scala> val BinOp(op,left,right)=exp
op: String = *
left: Expr = Number(5.0)
right: Expr = Number(1.0)
一個(gè) Case 序列( case squence,也成為可選項(xiàng))為包含在{}的代碼,它可以用在可以使用任何方程字面量的地方。從根本上來說 case 序列也是一個(gè)函數(shù)字面量,只是更一般化的函數(shù)。通常的函數(shù)只有一個(gè)入口點(diǎn)和一組參數(shù)。一個(gè) Case 序列可以有多個(gè)入口點(diǎn)和多組參數(shù)。每個(gè) Case 可選項(xiàng)都是函數(shù)的入口點(diǎn),而它對(duì)于模式為參數(shù)定義。其函數(shù)體為 Case 序列的右邊部分。
這里給出一個(gè)簡(jiǎn)單的例子:
val withDefault: Option[Int] => Int ={
case Some(x) =>x
case None => 0
}
這個(gè)函數(shù)定義了兩個(gè)可選項(xiàng),第一個(gè)選項(xiàng)匹配 Some 對(duì)象,第二個(gè)選項(xiàng)匹配 None。
scala> withDefault(Some(5))
res0: Int = 5
scala> withDefault(None)
res1: Int = 0
此外需要注意的是,一個(gè) Case 序列定義了一個(gè)部分函數(shù)( partial function ),如果你傳入一個(gè)該函數(shù)不支持的參數(shù),代碼會(huì)給出 Runtime 異常。比如我們定義下面一個(gè)部分函數(shù):
val second: List[Int] => Int = {
case x::y::_ => y
}
返回列表的第二個(gè)元素,系統(tǒng)會(huì)給出如下警告:
<console>:7: warning: match may not be exhaustive.
It would fail on the following input: List(_)
val second: List[Int] => Int = {
^
second: List[Int] => Int = <function1>
系統(tǒng)警告匹配不完全,比如函數(shù)無法匹配 List(1),List() 等,測(cè)試如下:
scala> second(List(1,2))
res7: Int = 2
scala> second(List(1))
scala.MatchError: List(1) (of class scala.collection.immutable.$colon$colon)
at $anonfun$1.apply(<console>:7)
at $anonfun$1.apply(<console>:7)
如果你需要測(cè)試某個(gè)部分函數(shù)是否定義,你就需要告訴編譯器你在使用部分函數(shù)。而類型 List[Int] => Int 代表了所有由列表到整數(shù)的變換。而如果我們需要定義由 List[int] 到 int 的部分函數(shù),需要使用 PartialFunction 來定義,例如:
val second:PartialFunction[List[Int],Int] = {
case x::y::_ => y
}
PartialFunction 定義了一個(gè) isDefinedAt 方法可以用來測(cè)試某種類型的部分函數(shù)是否定了。例如:
scala> second.isDefinedAt(List(5,6,7))
res0: Boolean = true
scala> second.isDefinedAt(List(1))
res1: Boolean = false
你也可以在 for 表示式中使用模式,比如我們之前定義的
val capitals = Map("France"->"Paris", "Japan"->"Tokyo","China"->"Beijing")
我們使用 for 表示式來枚舉國(guó)家和首都
for((country,city) <- capitals)
println("The captical of " + country + " is " + city)
The captical of France is Paris
The captical of Japan is Tokyo
The captical of China is Beijing
這個(gè)例子的 (county,city) 匹配都會(huì)成功,因?yàn)?capitals 的每個(gè)元素都是一個(gè)二元組。如果某些匹配不成功,則這些元素自動(dòng)跳過。比如:
val results=List(Some("apple"),None,Some("Orange"))
scala> for(Some(fruit) <- results) println (fruit)
apple
Orange