与断言相比,scala中的假设是什么意思?

时间:2011-11-03 22:41:22

标签: scala assert

Scala似乎定义了3种断言:assertrequireassume

据我所知,require的区别(与通用断言相比)是它专门用于检查输入(参数,传入消息等)。那么assume的含义是什么?

3 个答案:

答案 0 :(得分:48)

如果你看一下Predef.scala中的代码,你会发现这三个人的工作非常相似:

def assert(assertion: Boolean) { 
  if (!assertion) 
    throw new java.lang.AssertionError("assertion failed") 
} 

def assume(assumption: Boolean) { 
  if (!assumption) 
    throw new java.lang.AssertionError("assumption failed") 
} 

def require(requirement: Boolean) { 
  if (!requirement) 
    throw new IllegalArgumentException("requirement failed") 
} 

还有一些版本需要额外的参数用于报告目的(参见http://harrah.github.com/browse/samples/library/scala/Predef.scala.html)。

区别在于它们抛出的异常类型以及它们生成的错误消息。

然而,静态跳棋可以不同地对待这三种。意图是assert指定静态检查应该尝试证明的条件,assume将用于检查者可能认为要保留的条件,而require指定呼叫者必须确保的条件。如果静态检查程序发现违反assert,则认为它是代码中的错误,而当违反require时,它会假定调用方有错。

答案 1 :(得分:19)

差异

assert()和assume()之间的区别在于

  • assert()是一种记录和动态检查不变量的方法,而
  • 假设()旨在被静态分析工具使用

assert()的目标消费者/上下文正在测试,例如Scala JUnit测试,而assume()的消费者/上下文是“作为函数前后条件的合同样式规范的一种手段” ,意图是静态分析工具可以使用这些规范“(摘自scaladoc)。

静态分析/模型检查

在静态分析的上下文中,正如Adam Zalcman指出的那样,assert()是一个全执行路径断言,用于检查全局不变量,而assume()在本地工作以减少检查的数量。分析仪需要做。假设()用于假设保证推理的上下文,这是一种分而治之的机制,可以帮助模型检查员假设某些方法,以便解决当试图检查程序的所有路径时出现的状态爆炸问题可能需要。例如,如果你知道在你的程序设计中,函数f1(n1:Int,n2:Int)永远不会通过n2< n1,然后明确说明这个假设将有助于分析仪不必检查很多n1和n2的组合。

在实践中

在实践中,由于这样的整个程序模型检查器仍然主要是理论,让我们看一下scala编译器和解释器的作用:

  1. 假设()和assert()表达式都在运行时检查
  2. -Xdisable-assertions禁用assume()和assert()检查
  3. 更多

    关于这个主题的优秀scaladoc的更多内容:

    <强>断言

    提供了一组assert函数,用于记录和动态检查代码中的不变量。通过向-Xdisable-assertions命令提供命令行参数scala,可以在运行时省略断言语句。

    还提供了旨在用于静态分析工具的assert变体:assumerequireensuringrequire和确保旨在用作函数前后条件的合同样式规范的一种手段,意图是静态分析工具可以使用这些规范。例如,

    def addNaturals(nats: List[Int]): Int = {
      require(nats forall (_ >= 0), "List contains negative numbers")
      nats.foldLeft(0)(_ + _)
    } ensuring(_ >= 0)
    

    addNaturals的声明声明传递的整数列表应该只包含自然数(即非负数),并且返回的结果也是自然的。 require与assert的区别在于,如果条件失败,则函数的调用者应该责备而不是在addNaturals本身内进行逻辑错误。确保是一种断言形式,声明函数提供的关于它的返回值的保证。 )

答案 2 :(得分:5)

我是亚当斯的第二个回答,这里只是一些小补充:

当违反assume时,验证工具会默默地修剪路径,即不会更深入地跟踪路径。

因此,assume通常用于制定前提条件,assert以制定后置条件。

许多工具都使用这些概念,例如:模仿测试工具KLEE,软件限制模型检查工具,如CBMCLLBMC,部分也是基于抽象解释的静态代码分析工具。文章Finding common ground: Choose, Assert, Assume介绍了这些概念并试图将它们标准化。