Try tapFailure

(, en)

Add tapFailure to make logging easier:

// src/main/scala/ErrorUtil.scala
import scala.util.{Failure, Try}

object ErrorUtil {
  implicit class TryTapFailure[A](t: Try[A]) {
    def tapFailure(f: Throwable => Unit): Try[A] = t match {
      case Failure(ex) => f(ex); t
      case _ => t
    }
  }

  implicit class EitherTapLeft[L, R](e: Either[L, R]) {
    def tapLeft(f: L => Unit): Either[L,R] = e match {
      case Left(error) => f(error); e
      case _ => e
    }
  }
}
// src/test/scala/TryTapFailureSpec.scala
def somethingStupid = throw new RuntimeException("ABC")

val result = Try(somethingStupid)
  .tapFailure(ex => logger.error(ex)("I did something stupid"))
  .getOrElse("default")

logger.info(result)

Or use this when you don’t want the implicit construction:

// src/test/scala/TryTapFailureSpec.scala
def somethingStupid = throw new RuntimeException("ABC")

val result = Try(somethingStupid)
  .tap {
    case Failure(ex) => logger.error(ex)("I did something stupid")
    case _           =>
  }
  .getOrElse("default")

logger.info(result)

In case you don’t know tap, it comes from the scala.util.chaining package. To use it you can import it via

import scala.util.chaining._