문제

I have a recursive function count in Scala 2.9.2 that looks like this

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 ...
  }
}

On input Seq(('(', '(')) the function throws the following MatchError:

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

I investigated this by playing around with the code in the Scala console.

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)

It seems as if matching ('a', 'b')::rest (the second line) doesn't return an object of the correct type, since the Seq[(Char, Char)] is suddenly of type java.lang.Object which Scala then doesn't know how to match on.

What explains this behavior?

도움이 되었습니까?

해결책

The problem with your pattern matching is that you use extractors defined only for List class but passing to them Vector.

If you really need to match against every possible Seq, you may want to use general syntax:

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

(Don't be confused with -> arrow, 1 -> 2 is essentially the same as (1,2), but in this particular case much more readable: you will not mess usual braces with '(' and ')' like in Seq(('(',')'), ... ))

Otherwise, just strict your argument type to List[(Char, Char)].

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top