A few ways to implement a Swift like guard in Kotlin

Dai
AndroidPub
Published in
4 min readFeb 19, 2017

Before I started working with Kotlin, like most Android developers I developed applications in Java and in-between I learned Swift for iOS. One of the things I liked about Swift was the guard let syntax. Just seeing the guard keyword at the top of the method body was an instant indication that this function is going to return early or handle some potential errorneous parameter. So I started playing around with the ways you can achieve this in Kotlin. This guide is just to provide some ideas about how to achieve guard statements in Kotlin. Some people may not 100% agree with the ideas or may have some better solutions so feel free to post in the comments :).

If you want the TL;DR version with just the code examples, skip to the bottom.

Optionals are different in Kotlin

The way optionals work in Kotlin is very different to how they work in Swift. In Swift an optional is a special type, an Enum in fact. This Enum contains 2 cases, a Some(T) and a None, where T is the type being unwrapped from the Optional. When unwrapping the Optional, if there is a Some(T), the value will be returned. If there is a None, nil will be returned during an if let or guard let.

In Kotlin the compiler distinguishes between references that can be null and ones that can not be null by its ? in the type declaration. The compiler will then generate byte code that handles potential null references for you (provided you dont force (!!) access optional values). This makes the Kotlin compiler a little smarter since Optionals are not really “unwrapped”.

Thats a very simplified explanation so have a read around if you are curious to learn more about how Optionals work in both languages.

If

The first type of guard let we can do is a good old fashion if.

Thats it.

Since we have done a check for thing being null at the top of the function. The compiler is smart enough to know that anything accessing this property from that point on can safely assume it is not null. Meaning you no longer need to use the ? or !! to access any properties on the optional value. You can also use the is keyword to null check and smart cast.

However, both of these examples do not work for mutable (var) optional properties on class’s or in a situtaion where the var is not local to the null check. Since they could change, it prevents the compiler’s ability to smart cast.

So we need another solution. Kotlin contains so many nice features that writing if statements is a thing of the past. Im so used to not using them now I feel like im writing a hack when I do. So lets get rid of that if statement.

takeIf (Kotlin 1.1).

If you’re hipster enough and already using Kotlin 1.1 you may have noticed the takeIf general purpose extension function. takeIf does pretty much does what it says. It takes the value of the object it is being called on only if the given predicate is true.

So, in the example we are basically saying assign the val something to thing, only if it is not null (checked with the ?) and is less than 10. Otherwise return early.

Its awesome but not everyone is hipster enough to be on 1.1 yet, so lets continue.

let

Kotlin contains several general extension functions that work great as a guard. The first one we will look at is let. By using the ? and the let function we can execute code only if the optional value is not null and return the last statement from within the let block parameter.

We now create a val something with the String “hello” only if thing is not null, but if thing is null then the something value will also be null. And thats not what we want.

We could use the it as the last statement in the let block which would return the value of thing if it is not null, like this:

But lets do something else.

Elvis operator (?:)

Enter Elvis. Lets do that same bit of code but use the elvis operator. Which looks like this: ?.

The elvis operator is basically a more concise ternary. It works by executing the the first statement, if this is null it will execute the second statement. Its used mainly to return the statment value (like a ternary), but in the example above we are using it like a guard to return early. We can also use this in a even simapler case assign an Optional value to a new value or return early like so

apply

The let function returns the last statement, which is no use when we want to use the value of the optional we are checking. As I said, we could use the it keyword in the let block parameter but apply makes more sense here.

apply can be used in the same wayas let. The difference being apply always returns the value of its self i.e. this.

No matter what the last statement is within the apply block, It will always return the value of the thing variable and by using the elvis operator again we just return if apply returns null.

Extensions

If you really, really want to have a guard keyword then the next best thing is creating an extension function. This is exactly what let and apply are. Extension functions added to any type.

In the above example we have defined a guard general purpose extension function to T (T.guard). This basically means we are adding the guard extension function to any type. The guard takes a single lambda which is only called if the the object calling guard is null. We then use this lambda block to return early.

TL;DR

Use Kotlin’s if expressions to return early if something is null.
Use a smart cast check to assert something being a certain type and not null otherwise return early.
If you’e using Kotlin 1.1 use the takeIf general purpose extension function and a optional ? to return early if something is null and does much the given predicate.
Use the let syntax to return the value from within the let block if thing is not null. Otherwise ?: to return early if thing is null.
Simple return early using elvis.
Use apply to return this and return early if this is null.
Create an inline extension function called guard that calls a block with the property is null. Then return the value or early from within the lambda block if null.

Thanks for reading. Feel free to leave some suggestions in the comments.

--

--

Dai
AndroidPub

Engineering Manager (Client Platforms) @Plex