Update: Scala 2.8 has an annotation called elidable that will (when 2.8 is complete) allow one to remove method calls at compile time by setting a compiler flag. The assert, etc... methods are all marked with this flag and as a result can be removed at compile time for production environments.
Scala2.8
- scala> var called = 0
- called: Int = 0
- scala> called
- res0: Int = 0
- /*
- assert, require and assume have call by name parameters so the message is only
- calculated when the assertion fails.
- */
- scala> assert (called == 0, {called += 1; println("called is not 0")})
- scala> require (called == 0, {called += 1; println("called is not 0")})
- scala> assume (called == 0, {called += 1; println("called is not 0")})
- scala> called = 1
- called: Int = 1
- // demonstrating that the method is in fact called when the assertion fails
- scala> assert (called == 0, {called += 1; println("called is not 0")})
- called is not 0
- java.lang.AssertionError: assertion failed: ()
- at scala.Predef$.assert(Predef.scala:95)
- ...
-
- scala> called
- res4: Int = 2
- /*
- Require is intended to be used as a precondition of a method so
- it throws an IllegalArgumentException, not an AssertionError
- */
- scala> require (called == 0, {called += 1; println("called is not 0")})
- called is not 0
- java.lang.IllegalArgumentException: requirement failed: ()
- at scala.Predef$.require(Predef.scala:117)
- ...
-
- scala> called
- res6: Int = 3
- scala> assume (called == 0, {called += 1; println("called is not 0")})
- called is not 0
- java.lang.AssertionError: assumption failed: ()
- at scala.Predef$.assume(Predef.scala:107)
- ...
-
- scala> called
- res8: Int = 4
scala 2.7.7
- /*
- In Scala 2.7 the parameter is evaluated before the
- method is called so the side effect of the message causes
- the assertion to fail
- */
- scala> assert (called == 0, {called += 1; println("called is not 0")})
- called is not 0
- scala> called
- res2: Int = 1