2013-11-03 86 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 _' ... –