Published 2019-07-12.
Time to read: 2 minutes.
Every Scala source file enjoys a huge but invisible set of definitions that are defined in Predef
. This lecture discusses provides a gentle introduction to Predef
without getting into the weeds.

Scala’s Predef
defines many important implicit conversions and utility methods.
The sample code for this lecture can be found in
courseNotes/
.
assert and require
If you are a Java or Node.js programmer, then you’ll be glad to know that the assert
s
found in those languages are very similar to Scala’s assert
.
Predef.scala
defines the require
and assert
methods, which are used to enforce conditions during runtime.
require
throws IllegalArgumentException
if it evaluates the given condition as false.
If used properly, require
will only make itself known when some code has called it without proper setup or
with invalid parameters; you might consider this action similar to a HTTP 400 BadRequest
response from a web application.
Here is an example.
scala> def percentImprovement(a: Int, b: Int): Double = { require(b!=0) // Prevent divide by zero exception (b.toDouble - a.toDouble) / a.toDouble * 100.0 }
scala> percentImprovement(40, 50) res4: Double = 25.0
scala> percentImprovement(40, 0) java.lang.IllegalArgumentException: requirement failed at scala.Predef$.require(Predef.scala:327) at .percentImprovement(<console>:2) ... 28 elided
In contrast, when assert
makes itself known, and if assert was used properly, when the program you are running has reached an
inconsistent state an AssertionError
will be thrown; you might consider this action similar to a HTTP 500
InternalServerError
response from a web application.
The following code example, which computes factorial and shows good usage of both require
and assert
, is from
StackOverflow.
def factorial(i: Int): Long = { import scala.annotation.tailrec
require(i >= 0, "i must be non-negative") // this is for correct input
@tailrec def loop(k: Int, result: Long = 1): Long = { assert(result == 1 || result >= k) // this is only for verification
if (k > 0) loop(k - 1, result * k) else result }
loop(i) }
Removing assert’s Overhead for Production
If your program is compiled with -Xelide-below ASSERTION
or with -Xdisable-assertions
,
then the compiler will be prevented
from generating byte code for assertions.
If you have a large number of assert
s then the use of these switches can significantly reduce the size of your program’s runtime
memory image, and its performance will be also be improved.
Scala programmers should use assert
liberally to verify the invariants everywhere in their programs because there is no runtime penalty
in production if one of these compile-time switches is used.
You can rest assured that the pre- and post-conditions for every method and function call is validated in your program.
Unlike assert
, require
is not elidable via a compiler switch, so it should only be used in libraries.
require
is best used to inform the programmer of problems with preconditions for invocations of a library’s methods and functions.
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.