1. Previous: Chapter 2
  2. Next: Chapter 4
Kotlin: An Illustrated Guide • Chapter 3

Kotlin Conditionals: When and If

Chapter cover image

In real life, we do different things depending on the circumstances.

For example, if it’s raining outside, you’ll probably grab an umbrella. If it’s sunny outside, you might grab your sunglasses. We do different things depending on the weather.

Similarly, we often need our code to do different things in different situations, so in this chapter, we’ll look at Kotlin’s conditionals.

Goldilocks and the Three Branches

You might have heard the fairy tale of Goldilocks and the Three Bears.

Papa Bear, Mama Bear, and Baby Bear lived in a quaint house nestled in the woods. One day, after preparing some porridge for breakfast, the three bears decided to go out for a leisurely stroll. Meanwhile, a young girl named Goldilocks peeked in through the window and saw three bowls of porridge. Since she was hungry and saw nobody home, she decided to walk inside and taste the porridge for herself.

First, she tried Papa Bear’s porridge, and exclaimed, “It’s too hot!” Then she tried Mama Bear’s porridge, and complained, “It’s too cold!” Finally, she tried Baby Bear’s porridge, and found the temperature to be perfect. “It’s just right!” she said, and ate the entire bowl.

Let’s map out Goldilocks’ reaction to the three different bowls of porridge into a simple table:

Temperature Goldilocks’ Reaction
Greater than 60°C “It’s too hot!”
Less than 50°C “It’s too cold!”
Anything else “It’s just right!”

  1. When it’s above 60°C, she says, “It’s too hot!” 2. When it’s below 50°C, she complains, “It’s too cold!” 3. But anything in between, and she says, “It’s just right!”

We can write Kotlin code that will tell us which of these three things Goldilocks will say, based on the temperature of the porridge. In programming terms, the three different cases above—that is, the three different rows of the table—are called branches. We can visualize the branches as we’d see on a tree.

A tree with one branch for too hot, one branch for too cold, and one branch for just right. Temperature? It's just right! It's too hot! It's too cold! > 60 C < 50 C else

So far, when we’ve run the code that we’ve written, every line of code has run. But now we’re going to start writing code where only one of the branches will run each time. While the code is running, the path that is run—including the particular branch that it takes—is referred to as the execution path.

Here we can see the three possible execution paths that our Kotlin code could take, depending on the temperature.

The same tree shown three times. Each one has an arrow running from the trunk to one branch. Temper ature? It's too cold! < 50 C Temper ature? It's just right! else Temper ature? It's too hot! > 60 C

Code constructs that choose between different branches (e.g., different responses from Goldilocks) based on some condition (e.g., the temperature) are called conditionals. Kotlin has a couple of conditionals that we can use. Let’s take a look!

Introduction to when in Kotlin

Let’s look at that table again.

Temperature Goldilocks’ Reaction
Greater than 60°C “It’s too hot!”
Less than 50°C “It’s too cold!”
Anything else “It’s just right!”

A table like this is easy to read and understand. We can just scan down the left-hand column, and when we find the temperature of the porridge that Goldilocks is eating, we look to the right to see how she will respond.

Kotlin gives us a powerful conditional called when, which enables us to basically write that same table in our code. Here’s how it looks.

val temperature = 53

val reaction = when {
    temperature > 60 -> "It's too hot!"
    temperature < 50 -> "It's too cold!"
    else             -> "It's just right!"
}

Just to show how similar this is to our table, let’s add a little spacing and put the table next to it.

A when expression in Kotlin, with the same table next to it. The same code is found in Listing 3.1 above. val temperature = 53 val reaction = when { temperature > 60 -> "It's too hot!" temperature < 50 -> "It's too cold!" else -> "It's just right!" } Greater than 60°C “It’s too hot!” Less than 50°C “It’s too cold!” Anything else “It’s just right!”

This code looks almost identical to the table next to it—each line between the opening brace { and the closing brace } is just a row from the table. The reaction variable will be assigned a different value depending on the value of the temperature variable.

  • When the temperature is greater than 60, then reaction will be assigned "It's too hot!".

  • When the temperature is less than 50, then reaction will be assigned "It's too cold!".

  • Otherwise, reaction will be assigned "It's just right!".

To really understand when, let’s look at the different parts.

The different parts of a 'when' expression, explained below. val reaction = when { temperature > 60 -> "It's too hot!" temperature < 50 -> "It's too cold!" else -> "It's just right!" } 1. "when" keyword 4. "else" condition 2. conditions 3. values
  1. First, there’s when. This keyword tells Kotlin that we want to do something different depending on the circumstances. In this code, notice that when is an expression, so it is evaluated and can be assigned to a variable. In this case, it will evaluate to a string, which will be assigned to the reaction variable.

  2. Next, there are temperature > 60 and temperature < 50. These are called conditions. Conditions are expressions that evaluate to a Boolean. The first condition—temperature > 60—just asks the question, “is the value of the temperature variable greater than 60?” If so, then it evaluates to true. Otherwise it evaluates to false. When we need to compare numbers in Kotlin, we can use comparison operators like the greater-than sign > or the less-than sign <. See the chart below for more information.

  3. When the condition evaluates to true, then the when expression will evaluate to the value on the right side of the arrow ->.

  4. At the bottom, we have else, which is a catch-all branch that’s used in case none of the conditions above it evaluate to true.

The when expression is quite helpful, so Kotlin developers use it often. It also has some interesting characteristics. Let’s look at a few of them now.

The First True Condition Wins

Goldilocks just found some more porridge in the freezer, so let’s add another case for extremely cold temperatures.

val temperature = -5

val reaction = when {
    temperature > 60 -> "It's too hot!"
    temperature < 50 -> "It's too cold!"
    temperature < 0  -> "It's frigid!"
    else             -> "It's just right!"
}

In this code listing, because the temperature variable is set to -5, we might expect reaction to be "It's frigid!", but it’s actually "It's too cold!". Why is that?

Because Kotlin works through the when cases from top to bottom.

  1. First, temperature > 60 evaluates to false, because -5 is not greater than 60.

  2. Then, temperature < 50 evaluates to true, because -5 is indeed less than 50.

At this point, Kotlin uses "It's too cold!", because it found a matching condition. So, the third case—temperature < 0—is never evaluated.

In other words, the first condition that evaluates to true will win.

It’s easy to make sure that "It's frigid" is used when the temperature is below zero. Just put that case before the condition where the temperature is below 50 degrees, like in the following example.

val temperature = -5

val reaction = when {
    temperature > 60 -> "It's too hot!"
    temperature < 0  -> "It's frigid!"
    temperature < 50 -> "It's too cold!"
    else             -> "It's just right!"
}

Now, when we run this code, the temperature < 0 case will run before temperature < 50, so reaction will be "It's frigid!".

Exact Matches

Sometimes, instead of checking for a range of values (e.g., “anything greater than 60”, or “anything less than 50”) we only need to check for an exact match.

After the Three Bears discovered how much Goldilocks liked their porridge, they decided to write a cookbook that includes all of their family recipes. They opened an online store and began selling their books. Since the book is so popular, they wanted to give discounts to people who buy multiple copies of it.

Quantity Ordered Price Per Book
1 book $19.99 each
2 books $18.99 each
3 books $16.99 each
4 books $16.99 each
5 or more books $14.99 each

We could write a when expression for this table like this.

val quantity = 3

val pricePerBook = when {
    quantity == 1 -> 19.99
    quantity == 2 -> 18.99
    quantity == 3 -> 16.99
    quantity == 4 -> 16.99
    else          -> 14.99
}

However, Kotlin lets us shorten this up even more, by letting us specify a subject. Here’s how that looks.

val quantity = 3

val pricePerBook = when (quantity) {
    1    -> 19.99
    2    -> 18.99
    3    -> 16.99
    4    -> 16.99
    else -> 14.99
}

In this example, quantity is called the subject of the when expression. The subject can be any expression, but here we just used the variable quantity. Because we used quantity as the subject, we no longer had to put “quantity ==“ in each condition!

There’s one more shortcut that Kotlin gives us, allowing us to make this even more concise. Since the price-per-book for 3 books is the same as that for 4 books, we can put those conditions on the same line, separated by a comma.

val quantity = 3

val pricePerBook = when (quantity) {
    1    -> 19.99
    2    -> 18.99
    3, 4 -> 16.99
    else -> 14.99
}

Every Condition Must Be Accounted For

A when expression in Kotlin must include conditions for all possible values. For this reason, we say that a when expression must be exhaustive. This is also the reason that we usually need to include an else condition at the bottom.

Sometimes we can be exhaustive even without an else condition. For example, consider a Boolean expression. As we saw in Chapter 1, Boolean variables have only two possible values—true and false.

Kotlin knows that a Boolean value can only ever be true or false. So, as long as we have a branch for both of those conditions, then we won’t need an else branch.

val isLightbulbOn = true

val reaction = when (isLightbulbOn) {
    true  -> "It's bright"
    false -> "I can't see"
}

This isn’t the only occasion when we can omit the else condition. We’ll see this again when we learn about enum classes and sealed types.

The when expression is powerful, and Kotlin developers use it a lot! But it can be a bit heavy-handed for simple Boolean checks like in Listing 3.7 above. For these cases, Kotlin gives us a second kind of conditional.

if Expressions

We can make our lightbulb code even more concise by using an if expression instead of a when expression. if expressions are kind of like when expressions, but they have a single condition, and two cases—one for true and one for false. Here’s how it looks.

val reaction = if (isLightbulbOn) "It's bright" else "I can't see"

Let’s break down the parts of an if expression.

An 'if' expression in Kotlin. val reaction = if (isLightbulbOn) "It's bright" else "I can't see" "if" keyword "else" keyword condition true branch false branch

if is a keyword, like when and else. In the code above, isLightbulbOn is the condition that is evaluated.

  • If it evaluates to true, then reaction will be assigned "It's bright".

  • If it evaluates to false, then reaction will be assigned "I can't see".

It’s also fine to put the branches on different lines.

val reaction =
    if (isLightbulbOn)
        "It's bright"
    else
        "I can't see"

We can also use braces { and } around the branches. Doing so allows us to add statements to the branches, as shown below.

var isLightbulbOn = true

val reaction =
    if (isLightbulbOn) {
        isLightbulbOn = false
        "I just turned the light off."
    } else {
        isLightbulbOn = true
        "I just turned the light on."
    }

It’s possible to use if for more than one condition. For example, remember our price-per-book lookup in Listing 3.5? We could rewrite it into an if expression.

val pricePerBook =
    if (quantity == 1)
        19.99
    else if (quantity == 2)
        18.99
    else if (quantity == 3)
        16.99
    else if (quantity == 4)
        16.99
    else
        14.99

If you find yourself doing this, consider using a when expression instead. It’s easier to read.

when and if as Statements

So far, we’ve used the when and if conditionals as expressions, but you can also use them as statements. Here’s an example of using an if statement in Kotlin.

var wattage = 0
var lightbulbIsOn = true

if (lightbulbIsOn) {
    wattage = wattage + 12
}

A few interesting things to note here:

  • Unlike conditional expressions, conditional statements do not require an else branch. In the example above, if lightbulbIsOn is false, then the single branch that’s there—wattage = wattage + 12—will simply never run.
  • We did not assign this if statement to a variable, because it’s not possible to assign a statement to a variable, as we saw in Chapter 1.

Summary

Enjoying this book?
Order the paperback today!

Kotlin: An Illustrated Guide is now available on Amazon See the book on Amazon

Thanks to conditionals, the Three Bears were able to offer discounts to customers who bought multiple copies of their cookbook. And what became of Goldilocks? Well, she landed a new gig as their official taste tester!

You’ve already learned a lot about Kotlin—variables, types, expressions, statements, and functions. And in this chapter, you learned all about conditionals, including:

In this book, we’ve used a variety of types, such as integers, strings, and Booleans. In Chapter 4, we’ll start putting variables and functions together to create our very own types, using classes and objects—unlocking many exciting possibilities for us to start writing more advanced programs.

Thanks to David Blanc, Raheel Naz, and Mohit for reviewing this chapter.

Share this article:

  • Share on Facebook
  • Share on Reddit