Медленная Скала утверждает - PullRequest
12 голосов
/ 11 марта 2010

Мы недавно профилировали наш код, и мы столкнулись с несколькими раздражающими горячими точками. Они в форме

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 ]

16 голосов
/ 11 марта 2010

Ленивая оценка также имеет некоторые накладные расходы для созданного функционального объекта. Если ваш объект сообщения уже полностью создан (статическое сообщение), эти издержки не нужны.

Подходящий метод для вашего варианта использования будет в стиле 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 })
7 голосов
/ 13 марта 2010

Это по имени, я поменял его больше года назад.

http://www.scala -lang.org / узел / 825

Текущий Predef:

@elidable(ASSERTION)
def assert(assertion: Boolean, message: => Any) {
  if (!assertion)
    throw new java.lang.AssertionError("assertion failed: "+ message)
}
1 голос
/ 12 марта 2010

Томас ответил отлично, но если вам нравится идея последнего ответа, но вам не нравится нечитаемость, вы можете обойти ее:

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
0 голосов
/ 11 марта 2010

Попробуйте: assert( a==b, "%s is not equals to %s".format(a,b)) Формат должен вызываться только тогда, когда assert требуется строка. Формат добавляется в RichString посредством неявного.

...