Using range expressions with flow control statements
Apart from iterations, Kotlin range expressions can be useful when it comes to working with flow control statements. In this recipe, we are going to learn how to use range expressions together with if
and when
statements in order to tune up the code and make it safe. In this recipe, we are going to consider an example of using the in
operator to define a condition of an if
statement.
Getting ready
Kotlin range expressions—represented by the ClosedRange
interface—implement a contains(value: T): Boolean
function, which returns an information if a given parameter belongs to the range. This feature makes it convenient to use ranges together with control flow instructions. The contains()
function has also its equivalent operator, in
, and its negation, !in
.
How to do it...
- Let's create a variable and assign to it a random integer value:
val randomInt = Random().nextInt()
- Now we can check whether the
randomInt
value belongs to the scope of integers from0
to10
inclusive using range expressions:
if (randomInt in 0..10) { print("$randomInt belongs to <0, 10> range") } else { print("$randomInt doesn't belong to <0, 10> range") }
How it works...
We have used a range expression together with the in
operator in order to define a condition for the if
statement. The condition statement is natural to read and concise. In contrast, an equivalent classic implementation would look like this:
val randomInt = Random(20).nextInt() if (randomInt >= 0 && randomInt <= 10) { print("$randomInt belongs to <0, 10> range") } else { print("$randomInt doesn't belong to <0, 10> range") }
No doubt, the declarative approach using the range and in
operator is cleaner and easier to read, compared to classic, imperative-style condition statements.
There's more...
Range expressions can enhance use of the when
expression as well. In the following example, we are going to implement a simple function that will be responsible for mapping a student's exam score to a corresponding grade. Let's say we have the following enum class model for student grades:
enum class Grade { A, B, C, D }
We can define a function that will map the exam score value, in the 0
to 100
% range, to the proper grade (A
, B
, C
, or D
) using a when
expression, as follows:
fun computeGrade(score: Int): Grade = when (score) { in 90..100 -> Grade.A in 75 until 90 -> Grade.B in 60 until 75 -> Grade.C in 0 until 60 -> Grade.D else -> throw IllegalStateException("Wrong score value!") }
Using ranges together with the in
operator makes the implementation of the computeGrade()
function much cleaner and more natural than the classic equivalent implementation using traditional comparison operators, such as <
, >
, <=
, and >=
.
See also
- If you'd like to discover more about lambdas, the infix notation, and operator overloading, go ahead and dive into Chapter 2, Expressive Functions and Adjustable Interfaces