从List [(Char,Char)]到Object的奇怪类型转换

时间:2012-12-06 23:55:14

标签: java scala jvm jvm-languages

我在Scala 2.9.2中有一个递归函数count,看起来像这样

def count(traces: Seq[(Char, Char)], acc: (TP, TN, FP, FN)): (TP, TN, FP, FN) = {
  val (tp, tn, fp, fn) = acc
  traces match {
    case Nil => acc
    case ('(', '(')::rest => count(rest, (tp + 1, tn, fp, fn))
    case (')', ')')::rest => count(rest, (tp + 1, tn, fp, fn))
    case ('(', ')')::rest => count(rest, (tp, tn + 1, fp, fn))
    // ... exhaustive set of cases ...
  }
}

在输入Seq(('(', '('))上,该函数会抛出以下MatchError

scala.MatchError: Vector(((,()) (of class scala.collection.immutable.Vector)

我通过在Scala控制台中使用代码来调查这一点。

scala> val t = Seq(('a', 'b'), ('b', 'c'))
t: Seq[(Char, Char)] = List((a,b), (b,c))

scala> t match { case Nil => "h"; case ('a', 'b')::rest => rest }
res6: java.lang.Object = List((b,c))

scala> t1 match { case Nil => "h"; case ('a', 'b')::rest => rest }
scala.MatchError: List((b,c)) (of class scala.collection.immutable.$colon$colon)

似乎匹配('a', 'b')::rest(第二行)没有返回正确类型的对象,因为Seq[(Char, Char)]突然出现java.lang.Object类型,而Scala则不会我知道如何匹配。

是什么解释了这种行为?

1 个答案:

答案 0 :(得分:0)

模式匹配的问题在于您使用extractors defined only for List class但传递给它们。

如果你真的需要匹配每个可能的Seq,你可能想要使用一般语法:

   foo match {
     case Seq('(' -> ')',rest@ _* ) => println("The tail is" + rest)
   }

(不要与->箭头混淆,1 -> 2基本上与(1,2)相同,但在这种特殊情况下更具可读性:你不会把常见的大括号与{ {1}}和'(',如')'

否则,只需strict你的参数类型为List [(Char,Char)]。