为什么无法编译此代码
IndexedSeq(1, 2, 3) match {
case a :: b :: c => println("toto");
}
但是有可能使用Seq?
IndexedSeq(1, 2, 3).toSeq match {
case a :: b :: c => println("toto");
}
IndexedSeq.toSeq
方法只是演员!
答案 0 :(得分:4)
我不确定为什么第二个编译,但我知道它不起作用!
scala> IndexedSeq(1,2, 3).toSeq match {
case a :: b :: c :: nil => println("toto");
}
| | scala.MatchError: Vector(1, 2, 3) (of class scala.collection.immutable.Vector)
如果要对序列进行模式匹配,则需要使用+:作为连接运算符,或使用Seq(a,b,c)作为匹配的模式。见this answer
以下所有工作都符合要求:
IndexedSeq(1,2, 3).toSeq match {
case Seq(a, b, c) => println("toto");
}
IndexedSeq(1,2, 3) match {
case Seq(a, b, c) => println("toto");
}
IndexedSeq(1,2, 3).toSeq match {
case a +: b +: c => println("toto");
}
IndexedSeq(1,2, 3) match {
case a +: b +: c => println("toto");
}
答案 1 :(得分:1)
添加@ladams的答案。在IndexedSeq上调用toSeq只是指super,因为后者继承了前者。另外,您还可以通过以下方式提取值:
IndexedSeq(1, 2, 3) match {
case IndexedSeq(head, tail @ _*) => println("got match")
case _ => println("sth else")
}
此外,Seq只是一个返回适当集合的特征,例如
val s: Seq[Int] = 1 :: 2 :: 3 :: Nil
s: Seq[Int] = List(1, 2, 3)
因此,您可以将其与Cons匹配。而IndexedSeq返回一个Vector,它没有定义Cons运算符。
val s: IndexedSeq[Int] = IndexedSeq(1, 2, 3)
s: IndexedSequence[Int] = Vector(1, 2, 3)
答案 2 :(得分:1)
第一个示例没有编译,因为模式a :: b :: c
的类型是List[something]
,而选择器IndexedSeq(1, 2, 3)
的类型是IndexedSeq[Int]
。由于List
不是IndexedSeq
的子类型,因此编译器知道匹配可能成功并产生错误。如the language specification中所述(略微删除公式):
每种模式都可以通过两种方式输入。首先,尝试使用选择器类型作为其预期类型来键入模式。如果失败,则改为使用修改的期望类型键入,该类型通过用
undefined
替换类型参数的每次出现而得到。如果第二步也失败,则会产生编译时错误。
在第二种情况下,选择器的类型是Seq[Int]
,因此就编译器而言,可能在运行时变为List[Int]
,在这种情况下,它会成功。它可以发出匹配可能失败的警告(实际上它确实如此),但Scala设计者另有决定:仅当选择器的类型为sealed
时才会发出警告。