.filter after if else if else does not work on first if

Greetings!

Help me please undestand why this piece of code does not do what I expect it to do.

Code snippet

class SandboxKtTest {
    
    @Test
    fun test() {
        val a = 4
        val name = if (a < 5) {
            listOf(3,5,7)
        } else if (a >5) {
            listOf(1,2,3)
        } else {
            emptyList()
        }.filter {
            it == 3
        }
        println(name)
    }
}

Expectations:
the result is [3]

Actual:
the result is [3,5,7].

Observations:
if i change a to 5 and 6 correspondingly it will apply .filter. But not for the first branch. why?

reviewing bytecode confirms this.

Kotlin 2.1.0

Simplest solution, use a when

2 Likes

It’s because your cascaded if expression is equivalent to this:

    val name = if (a < 5) {
        listOf(3,5,7)
    } else {
        if (a >5) {
            listOf(1,2,3)
        } else {
            emptyList()
        }.filter {
            it == 3
        }
    }

It is easy to understand why the .filter binds only to the innermost if expression when you consider this:

val s = if (keepOriginal) str else str.upperCase()

Here, you wouldn’t expect .upperCase() to be applied to the whole if expression, but only to the else part. Similarly, the .filter above doesn’t apply to the whole outer if expression, but only to the else part of the outer if.

1 Like