話說模式匹配(8) 一個抽取器的例子
阿新 • • 發佈:2018-12-22
一個抽取器的例子
目前List的序列模式(sequence pattern)可以支援對前邊若干元素的匹配,比如:List(1,2,3,_*)
,如果想要實現 List(_*, lastEle)
這樣的形式,就需要通過自定義一個抽取器來實現了
// 自定義Extractor
object Append {
// 接受List結構
def unapply[A] (l: List[A]) = {
// 返回Tuple2:前邊的若干元素和最後一個元素
Some( (l.init, l.last) )
}
}
抽取器裡的unapply
方法,入參對應你想要進行匹配的物件,出參則是解構後的元素。
比如 list match { case Append(x,y) => }
list
對應unapply的入參,x,y
對應unapply
方法的出參。
為什麼unapply
方法的返回結果大多都使用Some
包裝一下,這其實是unapply
方法返回值的一些約束:
- 返回Boolean,那麼匹配時 case A() 裡面的true不用寫(也不能寫)
- 若原本想要返回型別為T,則使用Option[T],這樣是為了匹配時能夠判斷是否成功,Some[T] 成功,None不成功
- 若原本想要返回一組T1,…Tn,則使用Option[(T1,…Tn)]
現在看看上面自定義抽取器的使用例子:
scala> (1 to 9).toList match{ case _ Append 9 => println("OK") } OK scala> (1 to 9).toList match{ case x Append 8 Append 9 => println("OK") } OK
上面使用了中綴寫法,也可以寫成普通的構造方式,只是看起來沒有上面的舒服
scala> (1 to 9).toList match{ case Append(Append(_,8),9) => println("OK") }
OK
另外,如果覺得Append這個名字太囉嗦,抽取器object單例名稱也可以用符號表達,比如用”:>“來表示
object :> {
// unapply ...
}
這樣對匹配時的表達顯得更簡短一些
scala> (1 to 9).toList match{ case x :> 8 :> 9 => println("OK") } OK
另外,以”:“結尾的符號支援從右到左的操作方式,List的子類就採用了“::”這樣的名稱,以方便模式匹配(當然也是因為早期的一些函式式語言裡,如ML裡已經定義了::的形式,scala只是延續而已)。