我写了一个名为 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 ,一切正常。
有人能解释一下这种行为吗?
答案 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
。
...
toList
或Seq(someething: _*)
的变体将再次创建,List