Scala:toSeq vs Seq(某事:_ *)

时间:2012-12-23 22:34:28

标签: scala pattern-matching

我写了一个名为 extract 的函数,定义如下:

def extract(params: String): Seq[String] = {
  val result = params.split(",") map (param => param.trim())
  result toSeq
}

然后我在 extract 结果上执行模式匹配,如下所示:

extract(myInputString) match {
  case Nil => // do something
  case head :: Nil => // do something
  case head :: tail => // do something
}

每当我的模式匹配案例Nil => 分支时,我就会得到一个

scala.MatchError: WrappedArray(T) (of class scala.collection.mutable.WrappedArray$ofRef)

另一方面,如果我用提取函数中的 Seq(结果:_ *)替换结果toSeq ,一切正常。

有人能解释一下这种行为吗?

3 个答案:

答案 0 :(得分:4)

Nil::是仅与List类型的实例匹配的提取器。您传递的是Seq,这是一个更为一般的特征,可能是也可能不是List

使用Seq构建Seq(...)时,Scala默认构建List。同样不能说toSeq,它通常将底层集合封装在最适当的Seq接口中。例如,Iterator.toSeq产生Stream,而Array.toSeq产生WrappedArray

这就是为什么当你致电toSeq时你的代码不起作用的原因; String.split生成Array(它是原始Java String类中的方法),map维护其类型。您可以添加案例来处理Seq的实例,也可以让extract方法返回List

答案 1 :(得分:2)

对于一般Seq,您可以按如下方式进行匹配:

extract(myInputString) match { 
  case Seq() => ...
  case Seq(head) => ...
  case Seq(head, tail @ _*) => ...
}

Scala 2.10的Seq提取器与List上的提取器相同,因此只需将Nil替换为Seq(),将::替换为+:,它会工作:

extract(myInputString) match {
  case Seq() => ...
  case head +: Seq() => ...
  case head +: tail => ...
}

答案 2 :(得分:0)

现在,终极匹配

extract("a, b") match { 
  case Seq() => "0"
  case Seq(a, b, _*) => "many"
  case Seq(a, _*) => "1"
}

而且,我有点怀疑 - 这里的一切都是List

...

toListSeq(someething: _*)的变体将再次创建,List