7

私は、単純な try/catch ブロックを繰り返していることに気が付きました。

たとえば、yyyymmdd 形式の uri 文字列の日付を Joda-Time に変換する必要があるとします。標準の try/catch ブロックを使用すると、変換方法は次のようになります。

def ymd2Date(ymd: Option[String]) = ymd match {
  case Some(date) =>
    try { Right( ymdFormat.parseDateTime(date) ) }
    catch { case e => 
      log.info(e.getMessage)
      Left(None) 
    }
  case None => 
    Left(None) // no uri date param
}
val ymdFormat = DateTimeFormat.forPattern("yyyyMMdd")

十分に機能し、意図は明らかですが、重要でないすべてのイベントに対してこの種の try/catch ロギングを行うときは、それを DRY する方法を探します。検索の結果、scala.util.control.Exception に関するこのSO の投稿にたどり着きました。役に立ちますが、思い通りに機能させる/理解するのはまだ少し難しいです。平易な英語で言いたいのは、「catch some-action get-result log-error-type」です。

だから、私が興味を持っている(または有用であると理解している)control.Exceptionの部分に基づいてこれをハックしました:

class Catcher[T](f: => T) {   
  type Logger = (=> Any) => Unit

  def either[T]( logger: => Logger ) = {
    try { Right(f) }
    catch { case e => 
      logger(e.getMessage)
      Left(None)
    }
  }
}
def catching[T](f: => T) = new Catcher(f)

そして、try/catch の代わりに次のように使用します。

catching( ymdFormat.parseDateTime(date) ) either log.info

オプション、msg プレフィックスなどを追加できますが、おそらく、上記のように動作する control.Exception を取得する方法を見つけた方がよいでしょう。TypeSafe クルーは私よりも優れたコード世界を作成する予定です。書くことを想像するでしょう。

control.Exception を使用してこの種の構文を作成する方法を知っている人はいますか? catch ブロックで使用する名前でロガー関数を渡すことができますか?

control.Exception の「ユースケース」があれば素晴らしいのですが、このユーティリティはより高度な Scala 開発者向けであると感じています。

4

2 に答える 2

7

これはあなたが望むことをするはずです:

import scala.util.control.Exception
def log(logger: => Logger)(e: Throwable) = {
    logger(e.getMessage)
    None
}
Exception.allCatch withApply log(logger) apply Some(ymdFormat.parseDateTime(date))

Validationしかし、私の意見では、この種のものは Scalaz でより適切に処理されます。

于 2012-04-11T17:22:21.397 に答える
3

簡単な例:

import scala.util.control.Exception._

def throwingStuff {
  throw new Exception("Hello World!")
}

catching(classOf[Exception]).withApply{err => println(err.toString); None}.apply(Some(throwingStuff))

を使用withApplyして、クラスのアプリケーション ロジックをオーバーライドCatchし、ログへの書き込みなどを行うことができます。

于 2012-04-11T17:21:51.763 に答える