为什么不能与cons运算符匹配indexedSeq?

时间:2016-07-06 07:18:42

标签: scala

为什么无法编译此代码

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方法只是演员!

3 个答案:

答案 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时才会发出警告。