12

我们最近一直在分析我们的代码,并且遇到了一些烦人的热点。他们在表格中

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

因为其中一些断言可以在代码中多次调用,字符串 concat 开始累加。assert定义为:

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

为什么不将其定义为:

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

这样它就会懒惰地评估。鉴于它没有以这种方式定义,是否有一种内联方式来调用带有延迟评估的消息参数的断言?

谢谢

4

4 回答 4

17

延迟评估对于创建的函数对象也有一些开销。如果您的消息对象已经完全构造(静态消息),则此开销是不必要的。

适合您的用例的方法是 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 })
于 2010-03-11T13:44:33.463 回答
7

它是按名称命名的,一年多前我更改了它。

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)
}
于 2010-03-13T06:33:27.370 回答
1

托马斯的回答很棒,但如果您喜欢最后一个答案的想法但不喜欢不可读性,您可以绕过它:

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
于 2010-03-12T16:55:43.110 回答
-2

尝试:assert( a==b, "%s is not equals to %s".format(a,b)) 仅当断言需要字符串时才应调用格式。格式通过隐式添加到 RichString。

于 2010-03-11T14:32:07.100 回答