Медленная Скала утверждает
Недавно мы профилировали наш код и наткнулись на несколько раздражающих горячих точек. Они в форме
assert(a == b, a + " is not equal to " + b)
Поскольку некоторые из этих утверждений могут быть в коде, называемом огромным количеством раз, когда строка concat начинает суммироваться. assert
определяется как:
def assert(assumption : Boolean, message : Any) = ....
почему не определяется как:
def assert(assumption : Boolean, message : => Any) = ....
Таким образом это оценило бы лениво. Учитывая, что это не определено таким образом, существует ли встроенный способ вызова assert с параметром сообщения, который оценивается лениво?
Спасибо
4 ответа
Ленивая оценка также имеет некоторые накладные расходы для созданного объекта функции. Если ваш объект сообщения уже полностью создан (статическое сообщение), эти издержки не нужны.
Подходящий метод для вашего варианта использования будет sprintf-style:
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
Текущий Predef:
@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))
Формат должен вызываться только тогда, когда assert требуется строка. Формат добавляется в RichString через неявный.