AnZ
AnZ

Reputation: 1060

Kotlin - Elvis Operator misbehavior

Faced an interesting case when Elvis Operator ?: misconducts.

Imagine having something like this

base64ToBmp(str)?.let { <1> } ?: run { <2> }

and see that on some old phones and emulators <1> and <2> code was invoked.

This was acting like Bitmap failed to parse.

Anyone seen such behavior? Is there a logical explanation?

Upvotes: 1

Views: 247

Answers (2)

Marvin
Marvin

Reputation: 14255

let returns the value of the specified function block.

So the logical explanation is that <1> returns null. In that case the whole expression base64ToBmp(str)?.let { <1> } becomes null and the right hand side of the elvis operator (i.e. run { <2> }) will be evaluated.

A very simplified way of reproducing it would be:

"foo"?.let { print("<1>"); null } ?: print("<2>")
// Prints <1><2>

Depending on your actual use case, apply or also (which both return the context object itself) might be suitable (note that for apply the object reference is passed as this instead of it):

"foo"?.apply { print("<1>"); null } ?: print("<2>")
// Prints <1>

Upvotes: 6

Gustavo Pagani
Gustavo Pagani

Reputation: 6988

@Marvin's answer is correct, if you want to reproduce the scenario you could try this piece of code:

fun main() {
    fun someMethod(param: String?) = param

    fun letBlock(param: String): String? {
        println("<1>")
        return null
    }

    someMethod("some param")?.let(::letBlock) ?: run {
        println("<2>")
    }
}

The output is:

<1>
<2>

Upvotes: 2

Related Questions