3

私は通常、LiftWebのLoggableラッパーを介してSlf4JでScalaを使用します。これは、 1つの式のチェーンのみで構成される非常に一般的な方法を除いて、適切に機能します。

したがって、そのようなメソッドにロギングを追加したい場合は、単純に美しく、中括弧はありません

def method1():Z = a.doX(x).doY(y).doZ()

になる必要があります:

def method1():Z = {
  val v = a.doX(x).doY(y).doZ()
  logger.info("the value is %s".format(v))
  v
}

まったく同じではありませんか?私はこれでそれを解決することを試みました:

class ChainableLoggable[T](val v:T){
  def logInfo(logger:Logger, msg:String, other:Any*):T = {
    logger.info(msg.format(v, other))
    v
  }
}
implicit def anyToChainableLogger[T](v:T):ChainableLoggable[T] = new ChainableLoggable(v)

これで、より簡単なフォームを使用できます

 def method1():Z = a.doX(x).doY(y).doZ() logInfo(logger, "the value is %s") 

ただし、1つの余分なオブジェクトのインスタンス化とAnyからの暗黙的なオブジェクトは、コードの悪臭のように見え始めます。

誰かがより良い解決策を知っていますか?それとも私はこれを気にするべきではありませんか?

4

3 に答える 3

2

これは正しい方法のように見えます。特に、暗黙のタップがない場合(標準ライブラリにはありませんが、このようなものはかなり広く使用されておりtap、Rubyでは標準です):

class TapAnything[A](a: A) {
  def tap(f: A => Any): A = { f(a); a }
}
implicit def anything_can_be_tapped[A](a: A) = new TapAnything(a)

これにより、情報をそれ自体で暗黙的に持つことはそれほど重要ではありませんが、それを使用する場合は、それよりも改善されます

.tap(v => logger.info("the value is %s".format(v)))
于 2012-08-06T21:29:04.387 に答える
2

Scala 2.10には、まさに解決策があります。これは、暗黙のラッパーが提供するのと同じ効果を得ることができる新機能の値クラスですが、これらのラッパークラスのインスタンス化によるオーバーヘッドはありません。これを適用するには、次のようにコードを書き直す必要があります。

implicit class ChainableLoggable[T](val v : T) extends AnyVal {
  def logInfo(logger:Logger, msg:String, other:Any*) : T = {
    logger.info(msg.format(v, other))
    v
  }
}

内部的には、コンパイラは、引数リストの前にあなたを追加し、それに応じてその使用法を更新することlogInfoにより、Javaの一般的な「util」静的メソッドの類似物に変換します-参照してください、何もインスタンス化されません。v : T

于 2012-08-07T08:11:39.770 に答える
0

暗黙的な使用を避けたい場合は、このような関数を独自のロギング特性で定義できます。おそらく、暗黙のソリューションほどきれいではありません。

def info[A](a:A)(message:A=>String) = {
  logger.info(message(a))
  a
}

info(a.doX(x).doY(y).doZ())("the value is " + _)
于 2012-08-06T21:41:49.360 に答える