Pitfall with Kotlin’s Standard Library

Josh Feinberg
2 min readMay 30, 2018

Recently while refactoring a class from Java to Kotlin, a very interesting comment came up on my PR. I had used a let function call to run function A if the value was not null, else run function B. My coworker who left the comment noted that this may cause issues.

variable?.let {
functionA()
} ?: functionB()

I had used this technique before and couldn’t see what could be the problem. That was because I hadn’t realized what could be an unintended side effect of functionA() having a return value.

Here is a quiz for you: extending out that sample code, what do you think the following would return (assuming variable is not null)

fun functionA() {
print("hey ")
}
fun functionB() {
print("there")
}

The answer to this is pretty obvious. It will just return “hey”.

Now let’s change this up a bit:

fun functionA(): Int? {
print("hey ")
return null
}
fun functionB() {
print("there")
}

Here was the gotcha. Per the JavaDoc, let

Calls the specified function [block] with `this` value as its argument and returns its result.

This will return the result of functionA() which is null. That means that we will still follow the elvis operator and it will return “hey there”.

If you are curious about the behavior of all the Standard.kt functions, I highly recommend taking a look at Tomek Polański’s post about Standard.kt. As just a quick run through of what happens here.

functionA() originally returns Unit. This gets evaluated, Unit is not null, and we are fine. In the second example, functionA() returns a nullable value. Inside the let, it returns null and then when it goes to attempt to evaluate the elvis operator, it determines it is null and runs functionB().

This was a really interested behavior that I hadn’t though of and could have come up if we didn’t have proper code coverage during a refactor. It was good to see a real world example help how to decide which of these functions to use and taught me to be way more careful about getting to fancy with Kotlin.

--

--