Scala seems to define 3 kinds of assertions: assert
, require
and assume
.
As far as I can understand, the difference (compared to a
The difference between assert() and assume() is that
The intended consumer / context of assert() is testing, such as a Scala JUnit test, while that of assume() is "as a means of design-by-contract style specification of pre- and post-conditions on functions, with the intention that these specifications could be consumed by a static analysis tool" (excerpted from the scaladoc).
In the context of static analysis, as Adam Zalcman has pointed out, assert() is an all-execution-paths assertion, to check a global invariant, while assume() works locally to pare down the amount of checking that the analyzer needs to do. assume() is used in the context of assume-guarantee reasoning, which is a divide and conquer mechanism to help model checkers assume something about the method so as to tackle the state explosion problem that arises when one attempts to check all paths that the program may take. For example, if you knew that in the design of your program, a function f1(n1 : Int, n2:Int) is NEVER passed n2 < n1, then stating this assumption explicitly would help the analyzer not have to check a LOT of combinations of n1 and n2.
In practice, since such whole-program model checkers are still mostly theory, let's look at what the scala compiler and interpreter does:
More from the excellent scaladoc on this topic:
Assertions
A set of assert
functions are provided for use as a way to document and dynamically check invariants in code. assert statements can be elided at runtime by providing the command line argument -Xdisable-assertions
to the scala
command.
Variants of assert
intended for use with static analysis tools are also provided: assume
, require
and ensuring
. require
and ensuring are intended for use as a means of design-by-contract style specification of pre- and post-conditions on functions, with the intention that these specifications could be consumed by a static analysis tool. For instance,
def addNaturals(nats: List[Int]): Int = {
require(nats forall (_ >= 0), "List contains negative numbers")
nats.foldLeft(0)(_ + _)
} ensuring(_ >= 0)
The declaration of addNaturals states that the list of integers passed should only contain natural numbers (i.e. non-negative), and that the result returned will also be natural. require is distinct from assert in that if the condition fails, then the caller of the function is to blame rather than a logical error having been made within addNaturals itself. ensures is a form of assert that declares the guarantee the function is providing with regards to it's return value. )