Scala Pattern Matching с функцией Tailrec - PullRequest
0 голосов
/ 02 мая 2019

У меня есть следующая функция, которая выполняет Tailrec и пытается подсчитать количество символов в заданной строке:

  @scala.annotation.tailrec
  def letterCount(remaining: Seq[Char], acc: Map[Char, Int]): Map[Char, Int] = remaining match {
    case Nil => acc
    case x :: Nil => acc ++ Map(x -> 1)
    case x :: xs =>
      letterCount(xs.filter(_ == x), acc ++ Map(x -> xs.count(_ == x)))
  }

  letterCount("aabbccd".toSeq, Map.empty)

По какой-то странной причине она завершается ошибкой:

scala.MatchError: aabbccd (of class scala.collection.immutable.WrappedString)
    at $line87.$read$$iw$$iw$.letterCount(<pastie>:14)
    at $line87.$read$$iw$$iw$.liftedTree1$1(<pastie>:23)
    at $line87.$read$$iw$$iw$.<init>(<pastie>:22)
    at $line87.$read$$iw$$iw$.<clinit>(<pastie>)
    at $line87.$eval$.$print$lzycompute(<pastie>:7)
    at $line87.$eval$.$print(<pastie>:6)
    at $line87.$eval.$print(<pastie>)

Я не мог выяснить, в чем может быть проблема!Есть идеи?

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Как уже упоминалось в комментариях, Seq не является List.Seq не имеет элемента Nil и не имеет метода ::.

Если вы хотите использовать Seq[Char], вы можете сделать это.

@scala.annotation.tailrec
def letterCount(remaining: Seq[Char], acc: Map[Char, Int]): Map[Char, Int] = remaining match {
  case Seq() => acc
  case x +: xs =>
    letterCount(xs.filter(_ != x), acc ++ Map(x -> (xs.count(_ == x)+1)))
}

letterCount("aabbccd", Map.empty)

Обратите внимание, что вы не.toSeq String.Он автоматически интерпретируется как Seq[Char].

1 голос
/ 02 мая 2019

Здесь это работает:

  @scala.annotation.tailrec
  def letterCount(original: List[Char], remaining: List[Char], acc: Map[Char, Int]): Map[Char, Int] = remaining match {
    case Nil => acc
    case x :: Nil => acc ++ Map(x -> 1)
    case x :: xs =>
      letterCount(original, xs.filter(_ != x), acc ++ Map(x -> original.count(_ == x)))
  }
  letterCount("aabbccd".toList, "aabbccd".toList, Map.empty)

В качестве альтернативы, foldLeft также работает так:

"aabbccd".foldLeft[Map[Char,Int]](Map.empty)((map, c) => map + (c -> (map.getOrElse(c, 0) + 1)))
...