Медленное утверждение 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) = ....
Таким образом, он будет оценивать лениво.Учитывая, что это не определено таким образом, существует ли встроенный способ вызова утверждения с параметром сообщения, который оценивается лениво?
Спасибо
Решение
Отложенная оценка также имеет некоторые накладные расходы на созданный объект функции.Если ваш объект сообщения уже полностью создан (статическое сообщение), эти накладные расходы не нужны.
Подходящим методом для вашего варианта использования будет стиль sprintf:
assert(a == b, "%s is not equal to %s", a, b)
Пока есть специализированная функция
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
Текущая предопределенность:
@elidable(ASSERTION)
def assert(assertion: Boolean, message: => Any) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed: "+ message)
}
Ответ Томаса великолепен, но на тот случай, если вам нравится идея последнего ответа, но не нравится его нечитаемость, вы можете обойти это:
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 неявно.