When with "less than"


#1

Is it possible to do something like this:

val x:Int = //bla bla
return when(x){
   < 1     -> "less than 1"
   1       -> "one"
   else    -> "greater than one"
}

#2

The nearest I can get to that is the following though it’s not very elegant:

val x: Int = //bla bla
return when(x) {
   in Int.MIN_VALUE..0 -> "less than 1"
   1                   -> "one"
   else                -> "greater than one"
}

Personally, I’d just do:

val x: Int = //bla bla
return when {
   x < 1    -> "less than 1"
   x == 1   -> "one"
   else     -> "greater than one"
}

#3

I second the need for this as well. I was wanting the same thing just this week.

I know you can do the long way with the temporary variable but it feels ugly and I don’t like it.

In another thread I proposed the ability to refer to the parameter to the when as “it” to use as a target of method calls as in:

when(string)
{
    it.contains("A") -> println( "A")

perhaps that could be extended to include relational expressions involving it:

when(x)
{
    it < 1 -> "less than 1"

#4

I had a realization that it might be nice to do this with lambdas or function references:

E.g.:

when(string)
{
    { contains("A") } -> println( "A")

or

when(x)
{
    { it < 1 } -> "less than 1"

#5

The current Kotlin approach looks cleaner, to my taste:

when {
    x < 1 -> "less than 1"

#6

Doesn’t that nearly defeat the purpose of using a case based when statement?
Why does it support keywords such as “in” and “is”, but not operators? The syntax for that would be identical.


#7

In cases when it is a simple variable that is cleaner. But with more complex expressions that you only want evaluated once, it requires storing it in a variable to do that. After a little while doing FP and Kotlin you get to the point where it just feels dirty to actually create a named local variable.


#8

If you don’t want to assign an explicit name to your complex expression, then let is there to help you:

complexExpressionHere.let {
    when {
        it < 1 -> "less than 1"

#9

That still defeats the purpose of a case based when statement…
With what you’re proposing, you might as well just use if statements and avoid the bloat of creating the when.


#10

I know there are other ways to work around it, and all that we are saying is that it would be really nice if the compiler didn’t force you to do that. If I have a when with a value it would be nice to be able to refer to it inside the when as it and use it in more complex conditionals. The when(x) statement is just rather limiting in its capabilities and it would be nice if it were more powerful so I can just say:

    when(complexExpressionHere) {
        it < 1 -> "less than 1"

Unrelated to using it in conditions, your version also brought up an idea I suggested a while back, the idea of having an “extension” when that is the equivalent of when(x) but expressed as x.when. It would be useful in chains to easilly sort of do a conditional mapping.

So for example now you have to use let like you did:

someComplexExpressionChain
     .let {
        when(it) {
            is Foo -> "Foo"
            is Bar -> "Bar"
            else -> throw Error()
         }
     }
    .additionalChainedOperations

My suggestion with the addition of a “.when” extension would allow you to express that as:

someComplexExpressionChain
     .when {
        is Foo -> "Foo"
        is Bar -> "Bar"
        else -> throw Error()
     }
    .additionalChainedOperations

#11

Would that not add unnecessary complexity to how extensions work?
Unless what you are proposing is something within the actual language and not something users are able to create?


#12

Yes it would have to be a language level change to support the extension style when. Its definitely not something that can be just implemented in a library.