ScalaのTry
は非常に便利です。
そのパターンを使用したいのですが、すべての例外をログに記録します。
これどうやってするの?
次のヘルパーを定義します。
_import scala.util.{Try, Failure}
def LogTry[A](computation: => A): Try[A] = {
Try(computation) recoverWith {
case e: Throwable =>
log(e)
Failure(e)
}
}
_
その後、Try
を使用するのと同じように使用できますが、例外はlog(e)
を介してログに記録されます。
暗黙のクラスを使用してさらに微調整できます
def someMethod[A](f: => A): Try[A] = Try(f)
implicit class LogTry[A](res: Try[A]) {
def log() = res match {
case Success(s) => println("Success :) " + s); res
case Failure(f) => println("Failure :( " + f); res
}
}
これで、someMethod
を呼び出すことができ、その結果で次のようにlog
を呼び出すことができます。
scala> someMethod(1/0).log
Failure :( Java.lang.ArithmeticException: / by zero
そして
scala> someMethod(1).log
Success :) 1
もちろん、暗黙のクラス内のprintln
メソッドは、任意のロギングに置き換えることができます。
開始Scala 2.13
、連鎖操作 tap
を使用して、元の値を返しながら、任意の値に副作用(この場合はログ)を適用できます。
import util.chaining._
val x = Try("aa".toInt).tap(_.failed.foreach(println))
// Java.lang.NumberFormatException: For input string: "aa"
// x: Try[Int] = Failure(Java.lang.NumberFormatException: For input string: "aa")
または同等のパターンマッチングバージョン:
val x = Try("aa".toInt).tap { case Failure(e) => println(e) case _ => }
// Java.lang.NumberFormatException: For input string: "aa"
// x: Try[Int] = Failure(Java.lang.NumberFormatException: For input string: "aa")
tap
チェーン操作は、値(この場合はprintln
)に副作用(この場合はTry
またはログ)を適用します。 tap
が適用された元の変更されていない値(Try
)を返します。
def tap [U](f:(A)=> U):A