Throwing Exceptions
To signal an error from your own code, you must create an exception object
and then throw it. Kotlin allows you do to this directly, via the throw
statement, or indirectly, using one of its precondition functions.
Direct Use of throw
Consider the variance() function discussed earlier. Instead of returning
-1.0 to signal an error, you could do this instead:
fun variance(dataset: List<Double>): Double {
if (dataset.size < 2) {
throw IllegalArgumentException("not enough data")
}
...
}
Remember that exceptions change flow of control completely. No other part
of the variance() function will execute once the exception is thrown.
Remember that flow of control will be affected in the code that called
variance(), too.
Precondition Functions
You can also throw certain exceptions using the functions require(),
check() and error(). These typically require a little less code than
throwing the exception directly yourself, but their main benefit is that
they can make the intention of your code clearer.
require() will throw IllegalArgumentException if the boolean expression
specified as its first argument evaluates to false. The message associated
with the exception is provided by an optional second argument, which is
a lambda expression.
For example, the error handling for variance() could be written like
this:
fun variance(dataset: List<Double>): Double {
require(dataset.size > 1) { "not enough data" }
...
}
Notice how clear and readable this is.
check() will throw an IllegalStateException if the boolean expression
supplied as its first argument evaluates to false. The message associated
with the exception is provided by an optional second argument which is,
again, a lambda expression.
error() is the simplest of the three functions. It takes an error message
as its sole argument and throws an IllegalStateException with that message.
require() is a neat way of verifying the prerequisites needed for a
successful function call, before any further computation is attempted,
whereas check() is intended for use later on in a function’s code, for
the purpose of checking whether computation is proceeding as expected.
Together, these two functions fulfil a similar role to assert statements
in C & Python.