Search code examples
kotlinidioms

Kotlin's 'let' plus elvis, and accidental null return values


I was surprised today to learn that this take on apparently idiomatic code fails:

class QuickTest {

    var nullableThing: Int? = 55

    var nullThing: Int? = null

    @Test
    fun `test let behaviour`() {
        nullableThing?.let {
            print("Nullable thing was non-null")
            nullThing?.apply { print("Never happens") }
        } ?: run {
            fail("This shouldn't have run")
        }
    }
}

It happens because, combined with implicit return, nullThing?.apply{...} passes null to the let, and therefore the elvis operator evaluates on null and runs the second block.

This is pretty horrible to detect. Do we have an appropriate alternative beyond conventional if/else without this pitfall?


Solution

  • You could use also instead of let. also will return nullableThing, whereas let will return whatever the lambda returns.

    See this article: https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84 (point "3. Return this vs. other type").