Langsam Scala assert
-
19-09-2019 - |
Frage
Wir haben Profilierungs unseren Code vor kurzem, und wir haben über ein paar lästigen Hotspots kommen. Sie sind in der Form
assert(a == b, a + " is not equal to " + b)
Da einige dieser behauptet in Code sein kann, eine riesige Menge an mal die Zeichenfolge Concat beginnt aufgerufen hinzuzufügen. assert
ist wie folgt definiert:
def assert(assumption : Boolean, message : Any) = ....
Warum ist es nicht wie folgt definiert:
def assert(assumption : Boolean, message : => Any) = ....
Auf diese Weise es gemächlich bewerten würde. In Anbetracht, dass es nicht definiert auf diese Weise ist es ein Inline-Wege mit einer Nachricht param Aufruf behauptet, die träge ausgewertet wird?
Danke
Lösung
Verzögerte Auswertung hat auch einige Overhead für das Funktionsobjekt erstellt. Wenn Ihre Nachricht Objekt bereits vollständig aufgebaut (eine statische Meldung) dieser Aufwand ist nicht erforderlich.
Die entsprechende Methode für Ihren Anwendungsfall sei sprintf-style:
assert(a == b, "%s is not equal to %s", a, b)
Solange es ist eine speciaized Funktion
assert(Boolean, String, Any, Any)
Diese Implementierung hat keine Overhead oder die Kosten der var args Array
assert(Boolean, String, Any*)
für den allgemeinen Fall.
Die Implementierung toString lazily bewertet werden würde, aber nicht lesbar ist:
assert(a == b, new { override def toString = a + " is not equal to " + b })
Andere Tipps
Es ist von Namen, habe ich es vor über ein Jahr.
http://www.scala-lang.org/node/825
Aktuelle Predef:
@elidable(ASSERTION)
def assert(assertion: Boolean, message: => Any) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed: "+ message)
}
Thomas' Antwort ist groß, aber nur für den Fall gefällt Ihnen die Idee der letzten Antwort, aber nicht mögen die Unlesbarkeit, können Sie um es zu bekommen:
object LazyS {
def apply(f: => String): AnyRef = new {
override def toString = f
}
}
Beispiel:
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
Versuchen: assert( a==b, "%s is not equals to %s".format(a,b))
Das Format sollte nur aufgerufen werden, wenn die Assertion die Zeichenfolge muss. Format hinzugefügt RichString über implizit.