Kotlin: An Illustrated Guide • Chapter 3

# Kotlin Conditionals: When and If

In real life, we do different things depending on the circumstances. For example, if it’s raining outside, I’ll probably grab an umbrella. If it’s sunny outside, I’ll grab my sunglasses. I do different things depending on the weather.

Similarly, we often need our code to do different things in different situations.

In this chapter, we’ll learn all about conditionals in Kotlin, which will allow us to change the way the code runs depending on circumstances!

## 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 on 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 55°C “It’s too hot!”
Less than 40°C “It’s too cold!”
Anything else “It’s just right!”

Goldilocks responds differently depending on the temperature of the porridge.

1. When it’s above 55°C, she says, “It’s too hot!”
2. When it’s below 40°C, she complains, “It’s too cold!”
3. But anything in between, and she’ll say, “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. If it helps, you can visualize the branches like you’d see on a tree:

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 instead where only one of the branches will run each time. While your code is running, the path that is run - including the particular branch that it takes - is referred to as the execution path.

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

Code constructs that choose between different branches (e.g., different responses from Goldilocks) based on some condition (e.g., the temperature) are called conditionals.

So how can we write Kotlin code that tells us how Goldilocks will respond to each bowl of porridge? Kotlin has a couple of conditionals that we can use. Let’s check ’em out!

## Introduction to `when` in Kotlin

Let’s look at that table again.

Temperature Goldilocks’ Reaction
Greater than 55°C “It’s too hot!”
Less than 40°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 = 48

val reaction = when {
temperature > 55 -> "It's too hot!"
temperature < 40 -> "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.

As you can see, this looks almost identical to our table above! Each line between the opening brace `{` and the closing brace `}` is just a row from our table.

The `reaction` variable will be assigned a different value depending on the value of the `temperature` variable:

• When the `temperature` is greater than 55, then `reaction` will be assigned `"It's too hot!"`
• When the `temperature` is less than 40, 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:

1. First, there’s `when`. This is a keyword that tells Kotlin that you want to do something different depending on the circumstances. Note 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 > 55` and `temperature < 40`. These are called conditions. Conditions are expressions that evaluate to a Boolean.

`temperature > 55` just asks the question, “is the `temperature` variable is greater than 55?” If is indeed greater than 55, then it evaluates to `true`. Otherwise it evaluates to `false`. When you need to compare numbers in Kotlin, you can use things like the greater-than sign `>` or the less-than sign `<`. The fancy term for these is comparison operators. 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 match.

The `when` expression is quite helpful, and you’ll probably 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 > 55 -> "It's too hot!"
temperature < 40 -> "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`, you might expect `reaction` to be set to `"It's frigid!"`, but actually, it would be set to `"It's too cold!"`.

Why is that?

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

1. First, `temperature > 55` evaluates to `false`, because -5 is not greater than 55.
2. Then, `temperature < 40` evaluates to `true`, because -5 is indeed less than 40.

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 40 degrees, like this:

``````val temperature = -5

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

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

### Exact Matches

Sometimes, instead of checking for a range of values (e.g., “anything greater than 55”, or “anything less than 40”) 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.

Here’s the discount schedule:

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 the `when` statement 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 you shorten this up even more, by letting you 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 expression1, 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, like this:

``````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 you usually need to include an `else` condition at the bottom.

Sometimes you can be exhaustive even without an `else` condition. For example, consider a Boolean expression. As you recall, Booleans 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 cases, then we won’t need an `else` case.

``````val isLightbulbOn = true

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

This isn’t the only occasion when you 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 as a Kotlin developer, you’ll use it a lot! But it can be a bit heavy-handed for simple Boolean checks like for our lightbulb above. For these cases, Kotlin gives us a second kind of conditional.

## `if` Expressions

We can make our lightbulb example 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"``

And here are the different pieces:

`if` is a keyword, like `when`. `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"`

If you like, you may format this so that the branches are on different lines. For example:

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

You can also use braces `{` and `}` around the branches. Doing so allows you to add statements to the branches, like this:

``````var isLightbulbOn = true

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

Generally, as a Kotlin programmer, if you’ve got a single condition to check, you use an `if` expression. If you’ve got multiple conditions to check, you use a `when` expression.

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, like this:

``````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, stop!

Use a `when` expression instead!

## `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` to a variable, because as you recall, you cannot assign a statement to a variable.

## Summary

Enjoying this book?
Pick up the Leanpub edition today!

See the book on Leanpub

In just three chapters, you’ve already learned a lot about Kotlin! You know about variables, types, expressions, statements, and functions. And in this chapter, you learned all about conditionals, including:

• What branches and conditions are.
• How the `when` expression can be used to pick a different value in different situations.
• How an `if` expression can be a good fit for cases where you’ve only got two branches.
• How you can use `when` and `if` as statements.

In this book, we’ve used a variety of types, such as integers, strings, and Booleans. In the next chapter, we’ll start putting variables and functions together to create our very own types, using classes and objects. These concepts will open many exciting possibilities for us to start writing more advanced programs. See you then!

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

1. As of Kotlin 1.3, you can also capture the subject into a variable↩︎