Declarations in `when` statement


#1

I would find it convenient to have an ability to declare a variable inside when statement, like follows:

when (something) {
    FIRST -> { ... }
    val a = someExpression //usable in below branches
    SECOND -> uses(a)
    else -> uses(a)
}

when statement branches are checked from top to bottom if they are not Java switch, right?
Even in Java switch, I think, it would be OK to copy the variable declaration into each of the following branches.

Current grammar just prohibits val inside when, so it won’t be a breaking change.

I don’t think it’s good to allow arbitrary code between branches, it would be too confusing.

However, even this may mess up the code readability pretty well when abused. Thoughts?
Has this been considered or is it planned?


#2

No, this is not planned, and the semantics of this proposal seems fairly confusing to me. We do not always evaluate when branches sequentially, and it’s likely that future versions of Kotlin will use table-driven lookups in more cases than the current implementation, so copying the variable declaration into each branch would be the only way to implement it.

Then the question arises: what to do if a branch does not use the value of one of the variables defined above it? Do we copy the code of the initializer expression into the branch anyway, to ensure that the side effects of that expression still get evaluated? Or do we omit it, in order to reduce code size and improve performance, and lose the predictability? Also, can you refer to a in when conditions, and if you can, when does it actually get evaluated?

In other words, I’d be surprised if this is ever added into the language.


#3

@yole, thanks for the explanation.

I agree that the semantics of such a feature is not quite intuitive and would have to be thoroughly designed and well documented.

From my point of view, the most sensible option for this concept is to think of when as of equivalent to if-else-if chain. Ok, copying the initialization into branches will surely mess the order of computation (side effects from the initializer will come after side effects from the condition check), so it’s not an option in cases when a condition check might have side effects.

Yes, now I see the performance degradation and the severe limitation for non-sequential when.

As to whether the variable evaluation may be omitted, from the above I would say no (just performing the line of the code seems most meaningful), but (complicating things even further) there might be a modifier to do so, though I don’t have a clear idea on that.


#4

Piggybacking on this to say that being able to use it within when or to introduce bindings in the parens part of when would still be very very welcome: `it` within `when`