https://kotlinlang.org logo
Title
a

arekolek

05/13/2018, 7:23 PM
Is there any way to make Kotlin understand that this
when
expression is exhaustive?
fun test(x: Int): Int {
        assert(x in 1..3) // doesn't help
        if (x !in 1..3) throw IllegalArgumentException()  // doesn't help
        return when (x) {
            1 -> -1
            2 -> 0
            3 -> 1
        }
    }
a

Andreas Sinz

05/13/2018, 7:24 PM
nope
a

arekolek

05/13/2018, 7:24 PM
I guess I can just move the assertion to else
:yes: 3
but I was looking for something like
@IntRange
from support annotations (but to get compile time and runtime precondition check)
a

Andreas Sinz

05/13/2018, 7:25 PM
yes, I'd just have a
else -> throw Exception
f

frellan

05/13/2018, 8:10 PM
This is so anoyying, I get that it is a great warning sometimes but yeeech, I just want to use it like a bunch of if statements, not it always beeing exhaustive, currently I have this in my codebase
else -> {}
a

Andreas Sinz

05/13/2018, 8:25 PM
@frellan non-exhaustive in the sense that you ignore some cases on purpose?
f

frellan

05/13/2018, 8:30 PM
I have a number, and depending on whether an enum is some types, i multiply that number by different factors, I first define the number and only the types that match should modify it, I used a java switch before migrating my codebase
I dont want to initialise it in every when clause, thats just unnecessary
a

Andreas Sinz

05/13/2018, 8:45 PM
can you give me a small example?
f

frellan

05/13/2018, 9:20 PM
var multiplier = 10
when (amount.unit.type) {
  Type.VOLUME -> {
    multiplier *= food.density
  }
  Type.PACKAGE -> {
    multiplier *= food.density
  }
  Type.PIECE -> {
    multiplier *= food.density
  }
  Type.SPECIAL -> {
    multiplier *= food.density
  }
  Type.PORTION -> {
    multiplier *= food.density
  }
  else -> {}
}
return multiplier
Its different for every type, obviously. And there is more types than what I check for but for the rest of them I dont want to modify it
a

arekolek

05/13/2018, 9:31 PM
In your case I'd do:
return 10 * when(amount.unit.type) {
  Type.VOLUME, Type.PACKAGE, Type.PIECE -> food.density
  Type.SPECIAL -> special.density
  Type.PORTION -> portion.density
  else -> 1
}
(or you could actually list all remaining enum values, instead of
else
, if there's not many of them, I think there's even an intention action that does that for you if you don't have the else branch but you need one)
f

frellan

05/13/2018, 9:35 PM
Hmm, yeah its an expression, forgot that. Maybe I can do that, thanks for the tip!