Call for feedback -- switch expressions in JDK 12

Brian Goetz brian.goetz at oracle.com
Mon Apr 29 15:42:56 UTC 2019


> I had discussions about this with Manoj, and the focus was on "->" inside a switch *statement*. No question about switch expressions, here.

Thanks for the clarifications.

> In the recent past we stumbled on several issues with this combination, and we started to wonder, whether this particular combination carries its own weight:

Indeed, there are trade-offs here.

The “arrow” labels surely synergize better with expression switches than with statement switches, so it was a reasonable question to ask whether a wider split made sense.  The current feature could be described as 2x2, which is that switches can be expression or statement, and, orthogonally, use either “old” or “new” style labels.  All four quadrants are viable, though clearly we expect the (expression, new labels) quadrant to be the most popular.  

There were a few considerations that drove us to the 2x2 interpretation rather than the more ad-hoc “expression switches with new labels, or statement switches with old labels” design.  

 - There are statement switches that operate by side-effects, but which still are generally “one action per label”.  Bringing these into the fold with new-style labels makes these more straightforward and less error-prone.  

 - That the default for control flow is to fall through, rather than to break out, was an unfortunate early choice, and this is a matter of huge angst for users.  This seemed to be something that should be solved for switches in general, not just for expression switches.

 - It seemed more desirable to tease the desired benefits (expression-ness, better control flow and scoping) into orthogonal features, so that switch expression and statement could share more in common.  The more that switch expression and statement diverge (aside from the obvious), the more complex we make the language, and the more sharp edges there are for users to cut themselves on.  

All that said, we realize switch statements with -> labels are a little weird, especially if the statement on the RHS is not lexically short.  

> (1) Spec is complex (buggy), where it defines different rules of definite assignments for switch statements/expressions with ":" / "->”.

Please report bugs and propose improvements!

> (2) We have issues naming this thing, e.g., in compiler messages. Even JEP 325 & JEP 354 don't have a name for it but put the horse (syntax) before the cart (concept) by speaking of the "case L ->" switch label. The grammar term SwitchLabeledRule doesn't seem to be suitable for user-facing messages and explanations, either.

Please help suggest a better name!  

> (3) The recent proposal of admitting break-with in more contexts would create new confusion if the following were admitted:
> 
> //---
> int result = switch (in1) {
>    case 0 -> {
>            switch (in2) {
>                  case 0 -> break-with 13; // line 4
>                  default -> System.out.println("default");
>            }
>            break-with 14;
>        }
>    default -> 42;
> };
> //—

This is a difficult tradeoff.  On the one hand, allowing break-with to “tunnel through” a switch statement (just as break tunnels through an if statement) is perfectly unambiguous, and potentially useful. (I suspect it would be used more from for loops, rather than from nested switches.)  On the other hand, it is possible to write complex code using nonlocal control flow that is confusing.  

> Other related concepts that don't exactly align with switch statement with ->:
> - lambdas can be void compatible and/or value compatible.
>  This concept *could* be applied to switch also, but isn’t.

Good point!  

> - we already have the concept of ExpressionStatement/StatementExpression,
>  for things that swing both ways, but switch does not participate in this, either.
> 
> IMHO, these are several bad smells, all caused by the same combination of constructs, so we were asking what benefits would possibly outweigh those bad smells.
> 
> Yet another way of asking: to what degree are switch statement and switch expression (intended to be) the same animal, or disjoint concepts?

This I can answer clearly: we are surely better off maximizing their commonality. Gratuitous divergence is just pure accidental complexity.  Their differences should be related to their essential differences, rather than just the style of code we think we want to encourage in 2019.  

SO given that, do you have suggestions as to how to improve the specification so as to gain the benefits of being as similar as is reasonable, while avoiding some of the pitfalls you raise?  Because most of the pitfalls seem largely accidental and fixable.






More information about the jdk-dev mailing list