スローScalaのアサート
-
19-09-2019 - |
質問
我々は最近、我々のコードをプロファイリングしてきたし、我々はいくつかの厄介なホットスポットに遭遇しました。彼らは形にしている。
assert(a == b, a + " is not equal to " + b)
これらのいくつかは、文字列の連結がアップ追加し始め倍の膨大な量と呼ばれるコードにすることができ主張するので。 assert
は次のように定義されます:
def assert(assumption : Boolean, message : Any) = ....
なぜそれは、次のように定義されていません
def assert(assumption : Boolean, message : => Any) = ....
これを遅延評価するでしょうその方法。それはそのように定義されていないことを考えると遅延評価されたメッセージのparamと主張呼び出すのインライン方法はありますか?
おかげ
解決
遅延評価も作成関数オブジェクトのためのいくつかのオーバーヘッドがあります。あなたのメッセージオブジェクトがすでに完全に(静的メッセージ)を構築している場合、このオーバーヘッドは不要です。
あなたのユースケースのための適切な方法は、sprintfのスタイルになります:
assert(a == b, "%s is not equal to %s", a, b)
限りspeciaized関数が存在するように
assert(Boolean, String, Any, Any)
この実装はオーバーヘッドまたはVARのargs配列のコストを持っていない
assert(Boolean, String, Any*)
一般的なケースのための
の実装のtoStringは遅延評価が、読めないことになります。
assert(a == b, new { override def toString = a + " is not equal to " + b })
他のヒント
これがあることで、名前、私は一年以上前に、それを変更します。
http://www.scala-lang.org/node/825する
現在のPredefます:
@elidable(ASSERTION)
def assert(assertion: Boolean, message: => Any) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed: "+ message)
}
トーマスの答えは素晴らしいですが、念のためにあなたが最後の答えのアイデアを気に入ったがunreadabilityを嫌い、あなたはそれを回避することができます:
object LazyS {
def apply(f: => String): AnyRef = new {
override def toString = f
}
}
例:
object KnightSpeak {
override def toString = { println("Turned into a string") ; "Ni" }
}
scala> assert(true != false , LazyS("I say " + KnightSpeak))
scala> println( LazyS("I say " + KnightSpeak) )
Turned into a string
I say Ni
試してみてください。assert( a==b, "%s is not equals to %s".format(a,b))
アサートが文字列を必要とするときのフォーマットにのみ呼び出す必要があります。フォーマットは、暗黙の経由RichStringに追加されます。