2013-11-03 91 views
16

在閱讀post關於如何使用Vector(或任何實現Seq的集合)的模式匹配之後,我測試了此集合上的模式匹配。匹配矢量模式匹配「case Nil」

scala> x // Vector 
res38: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3) 

scala> x match { 
    | case y +: ys => println("y: " + "ys: " + ys) 
    | case Nil => println("empty vector") 
    | } 
<console>:12: error: pattern type is incompatible with expected type; 
found : scala.collection.immutable.Nil.type 
required: scala.collection.immutable.Vector[Int] 
Note: if you intended to match against the class, try `case _: <none>` 
       case Nil => println("empty vector") 
        ^

這裏的dhg的回答,解釋+:

object +: { 
    def unapply[T](s: Seq[T]) = 
    s.headOption.map(head => (head, s.tail)) 
} 

REPL向我表明

scala> Vector[Int]() == Nil 
res37: Boolean = true 

...那麼,爲什麼我不能用一個Vectorcase Nil聲明?

回答

24

比較Vector[Int]() == Nil是可能的,因爲您比較的類型沒有任何限制;允許的equals的執行情況的集合,在另一方面,通過元件相比不論執行集合類型的元素:

Vector(1, 2, 3) == List(1, 2, 3) // true! 

在模式匹配,則不能有一個空列表的情況下(Nil)當類型與列表無關時(它是Vector)。

你可以這樣做但是:

val x = Vector(1, 2, 3) 

x match { 
    case y +: ys => println("head: " + y + "; tail: " + ys) 
    case IndexedSeq() => println("empty vector") 
} 

但我建議只在這裏使用默認的情況下,因爲如果x沒有一個頭元素,它必須在技術上空:

x match { 
    case y +: ys => println("head: " + y + "; tail: " + ys) 
    case _ => println("empty vector") 
} 
+0

謝謝你的回答。作爲旁白的後續行動,在模式匹配中通常使用「全面通緝」「_」來表示一種好的或不好的做法?我理解你在這裏使用'_'的原因,因爲用你的話說,「但是我建議僅僅在這裏使用默認情況,因爲如果x沒有head元素,它必須在技術上是空的。」 –

+2

抓住所有可以意外地捕獲比你想象的更多的案件。對於明確枚舉(密封)類型,我建議不要使用'_'。例如,用'List'確實有編譯器檢查:'def foo(xs:List [Any])= xs match {case head :: tail =>「yes」}'給你警告,'def foo(xs: Vector [Any])= xs match {case head +:tail =>「yes」}'不。對於'List',我將使用'case Nil',對於索引seq'c​​ase _' ... –