Медленно Scala утверждать

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

assert(a == b, a + " is not equal to " + b)

Потому что некоторые из этих утверждений могут быть в коде, называемом огромным количеством раз, когда строка concat начинает складываться. assert определяется как:

def assert(assumption : Boolean, message : Any) = ....

почему он не определяется как:

def assert(assumption : Boolean, message : => Any) = ....

Таким образом, это будет оцениваться лениво. Учитывая, что он не определен таким образом, существует ли встроенный способ вызова assert с параметром message, который оценивается лениво?

Спасибо

Ответ 1

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

Соответствующим методом для вашего случая использования будет стиль 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 })

Ответ 2

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

http://www.scala-lang.org/node/825

Current Predef:

@elidable(ASSERTION)
def assert(assertion: Boolean, message: => Any) {
  if (!assertion)
    throw new java.lang.AssertionError("assertion failed: "+ message)
}

Ответ 3

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

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

Ответ 4

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