Search code examples
scalarecursiontail-recursiontry-catch-finally

Scala tail recursion from finally block


I want to apply a function f to each element of a List and not stop at the first error but throw the last error (if any) only:

@annotation.tailrec
def tryAll[A](xs: List[A])(f: A => Unit): Unit = {
  xs match {
    case x :: xt =>
      try {
        f(x)
      } finally {
        tryAll(xt)(f)
      }
    case _ =>
  }
}

But, the above code does not compile - it is complaining that this function is not tail recursive. Why not?


Solution

  • This solution iterates over all elements and produces (throws) the last error if any:

    def tryAll[A](xs: List[A])(f: A => Unit): Unit = {
      val res = xs.foldLeft(Option.empty[Throwable]) {
        case (maybeThrowable, a) =>
          Try(f(a)) match {
            case Success(_) => maybeThrowable
            case Failure(e) => Option(e)
          }
      }
    
      res.foreach(throwable => throw throwable)
    }