I’m aware that I’m not the first person to bring this up, but all discussions on the matter I’ve found are several years old.
When writing a when
statement, it’s often the case that we’re dealing with numeric values (or generally: Comparable<T>
s). However, a when
case in Kotlin currently cannot use any comparison operators. For example, the following sadly doesn’t work:
val myInteger: Int = randomInt()
val description = when(myInteger){
< 0 -> "negative"
0 -> "zero"
> 0 -> "positive"
}
I’ve seen various workarounds, but they’re all very unsatisfying. Using in
and is
is acceptable, but comparison operators somehow are not?
Here are a couple of workarounds (I deem none of them acceptable):
// problematic: "myInteger" is clearly the subject of the "when" expression,
// yet the "when" is stated to have no subject.
val description = when {
myInteger < 0 -> "negative"
myInteger == 0 -> "zero"
myInteger > 0 -> "positive"
}
// lipstick on a pig, doesn't solve the underlying problem
val description = myInteger.let {
when {
it < 0 -> "negative"
it == 0 -> "zero"
it > 0 -> "positive"
}
}
// this one actually does the trick, but readability is poor
val description = when(myInteger) {
in Int.MIN_VALUE ..< 0 -> "negative"
0 -> "zero"
in 1..Int.MAX_VALUE -> "positive"
}
Can we please reconsider that it might be a good idea to have comparison operators on when
subjects?
3 Likes
You can create some named ranges to simplify for this case:
val Int.Companion.negative get() = MIN_VALUE..<0
val Int.Companion.positive get() = 1..<MAX_VALUE
val Int.description get() = when(this) {
in Int.negative -> "negative"
in Int.positive -> "positive"
else -> "zero"
}
But in general, your point is valid
2 Likes
@dalewking that’s a new one, haven’t seen that solution before! 
However, as shown in the opening post, I’d like the exhaustiveness check to work on it as well without using “else”. And I think for this construction it would be very difficult for the compiler to verify that because of the indirection.
1 Like
I guess it could be a parser restriction.
when (x) {
0 -> -1
< 0
+ 1 -> false
}
could read
when (x) {
0 -> -1 < 0
+1 -> false
}
or
when (x) {
0 -> -1
< 0 + 1 -> false
}
Interesting enough, the compiler will accept
if (x
> 2) println(true)
although the kotlin grammar says

thus only allows a LF after the comparison operator and will reject the when
example stated above.
1 Like
@tango24 if there is an ambiguity, this wouldn’t be the first place in the kotlin syntax where the presence or absence of a newline character makes a difference. I would happily accept that.
Another option (a bit Scalaish) is to have sealed classes like “PositiveInt”, “NegativeInt”, “Zero” (or better domain-specific like “StockGrowth”/“TemperatureRaise”/whatever).
Then in your code base you don’t need such “whens” at all because you are guaranteed to have a value which belongs to a specific case. Then use some kind of polymorphism to switch between cases.