Fall through in when


#1

Currently it’s not possible to emulate the fall through structure of a Java switch statement cleanly. There are example workarounds in this Stack Overflow Article, but none of them are clean, and all add levels of indirection, as well as computational overhead.

Allowing fallthrough in switch statements is a cause of bugs, and not allowing it by default in Kotlin was a good call. However, it should be possible to use fall through behavior when explicitly asked for.

This could be handled using a new keyword “fallthrough” which would be syntactically easy to read. It could also be handled through structure of curly braces, or any other mechanism.

Here is an example:

when(oldVersion) {
1 -> upgradeFromV1(); fallthrough
2 -> upgradeFromV2(); fallthrough
3 -> upgradeFromV3()
}

Is this a good idea? Is something like this possible?


#2

It looks like the following code is much better at expressing this intent:

if (oldVersion <= 1) upgradeFromV1()
if (oldVersion <= 2) upgradeFromV2()
if (oldVersion <= 3) upgradeFromV3()

The best thing about this approach (as opposed to when) is that it makes clear on how to abstract it to make it easier to extend for an arbitrary list of supported versions:

supportedVersions
    .takeLastWhile { oldVersion <= it.versionNumber }
    .forEach { it.upgradeFromThisVersion() }

#3

We have a tentative plan to support the continue keyword in when statements to support fallthrough. It’s not scheduled for any specific future version of Kotlin, though.


#4

I think that takeLastWhile is a good solution, and I don’t disagree that multiple if-statements is very clear, but there are computational costs to both.

Admittedly, upgrading database versions isn’t a great example when talking about computational overhead. One of the great advantages of a switch statement is that the code can be laid out to minimize conditional branching. However, both of these solutions have a potential branch for every case.


#5

A continue would be good, but not sure if as good looking as something like:

// Paint first 8 stars
fun fillRating(stars: Array<View>, rating: Int // pass 7) {
    when(rating) {
        in 0 .. 9 -> stars[rating].visibility = View.VISIBLE continue (fall through from 0 to 7)
    }
}

I know this is a unidimensional case, but if fall through is very handy when you have multiple cases for example painting stars in different colors, or any other case where you would want to group multiple switchs, whiles, fors.