Wow this was very unexpected, am I weird for assum...
# getting-started
s
Wow this was very unexpected, am I weird for assuming it should’ve been this way? For code
Copy code
val x = 0
val result1 = if (x == 0) {
    10
} else if (x < 5) {
    5
} else {
    7
}.coerceAtMost(6)
println("$result1 <- should be 6 not 10?")
It actually prints 10, not 6, as the
coerceAtMost(6)
somehow only applies to the last 2 branches in the if-else chain but not the first one? More examples here https://pl.kotl.in/COmzDaqZB with various number of if-else branches where it seems to work only for the last 2 branches, this is like suuuuuper odd, what am I missing here? 🥴 My assumption here was that the result of the entire if expression is evaluated and then passed inside
coerceAtMost()
. Or even if that were not the case, I would expect it to only count the last
else
case, but not the one above it too.
😢 1
That’s the second time I’ve seen that come up this week. I think this issue needs more upvotes.
j
This is theoretically not a single if expression, but one
if
and a nested one in the
else
. But honestly I never had a problem with that for 2 stylistic reasons. 1. Those chains are nicer to read as
when
expressions, which are single expressions 2. Calling a method at the end of a block like this really doesn't look good to me, and I would certainly extract either a variable or a method for this
m
Not only this week, it has come up pretty often in the last few months. Even if you know why it doesn't work as one might expect, the fact that people are confused warrants enough reason to look at it. (The whole range until comes to mind) In the meantime, do it with a when, which is arguably more understandable 🙂
Copy code
val result = when{
    x == 0 -> 10
    x < 5 -> 5
    else -> 7
}.coerceAtMost(6)
s
Aha! So it takes the last expression like so
Copy code
/*} else */ if (num < 0) { // ignores everything before the if here 
        "negative"
    } else {
        "zero"
    }
and applies it there. This does make a lot of sense then with this knowledge, but I can’t imagine anyone intuitively expecting this to be the way it works. Will go with a when expression here, or simply save the result of the if expression in a variable and apply coerceAtMost to that one, but yeah this is crazy. This could almost be the first time I’ve seen such an unexpected behavior from Kotlin where I wasn’t expecting it at all. Thanks everyone for the quick responses. People certainly seem to have opinions on this topic, 3 responses within 2 minutes is quite unusual 😂 But I upvoted the issue, at least an IDE warning should be warranted there, suggesting switching to a when expression instead.
plus1 2
l
the if else chain is essentially syntactic sugar over
Copy code
if(condition1) {
    ...
} else {
    if(condition2) {
        ...
    } else {
        if(condition3) {
            ...
        } else {
            ...
        }
    }
}
if that helps to understand it more visually.
s
Yeap, I never thought of it this way before but after this thread I see it 👀