Switch expressions -- some revisions

Brian Goetz brian.goetz at oracle.com
Thu Dec 14 22:12:30 UTC 2017

>     So we dusted off an old idea, which we'd previously explored but
>     which had some challenges, which is to use "break" with an operand
>     instead of "return" to indicate local return in switch
>     expressions.  So:
>         int y = switch(abs(x)) {
>             case 1 -> 1;
>             case 2 -> 2;
>             case 3 -> 3;
>             default -> {
>                 println("bigger than 3");
>                 break x;
>             }
>         };
> The choice of `break` here feels very uncomfortable to me. The whole 
> nature of expression switch is that you never have to mess around with 
> your control flow the way you do in statement switch. The idea that 
> you're "breaking" out of anything doesn't apply in this world, so it 
> just feels opportunistic to repurpose the keyword for something else.

No, it's not a repurposing -- it's the same semantics, extended to the 
value-bearing nature of an expression switch.

Let's make an analogy with "return".  Return has two forms:
   - "return" -- for void methods
   - "return e" -- for non-void methods

In both cases, it means "stop executing the enclosing method right now, 
and here's a final value to give to whoever got me started, if they're 
expecting a value."

So for "break" in switch, we have:
  - "break" -- for statement (void) switches
  - "break e" -- for expression (non-void) switches

In both cases, it means "stop executing the enclosing switch now, and 
here's a final value to give to whoever got me started, if they're 
expecting a value."

Using "return" here to mean "yield value locally from expression" is the 
repurposing.  With lambdas we could kind of get away with it because we 
knew at some level lambdas were going to be translated down to methods, 
but it was always uncomfortable.  With statement switches, it's even 
more of a stretch.  Sure, you can squint and say "the case arm is like a 
lambda whose args are the binding variables and whose body is the RHS", 
but it does require squinting.

> I understood `return` and I'm trying to figure out if the problems you 
> describe with it are really that harmful.
> And if they are that harmful... would we consider just removing the 
> keyword and allowing this block to end with a naked expression?  i.e., 
> you have zero or more statements, followed by one expression. I don't 
> know if this is good or bad.

Definitely not.  Yes, I know it works in other languages (where 
everything is an expression), but I think this is a non-starter for Java.

>     int y = switch(abs(x)) {
>         case 1 -> 1;
>         case 2 -> 2;
>         case 3 -> 3;
>         default:
>             println("more than 3");
>             break x;
>     };
> Not liking the mixed motif here.

The mixed delimiters are the warty bit of it, true.  But what this does 
is define expression-switch directly on top of existing switch, yielding 
a result which feels smaller and far less "nailed on the side" than the 
previous proposal.

To summarize (2) + (3); pretend you never saw the original proposal with 
blocks.  It's like saying:

  - We're going to take existing switch, and extend it to work both as a 
statement and an expression;
  - DA analysis gets extended to ensure that expression switches are 
  - In an expression context, break takes an operand to indicate the 
value to be yielded up as the value of the expression;
  - Plus the nice -> e syntactic shorthand for the overwhelmingly common 
case, so you almost never have to type "break".

And that's it -- nothing else new.  It's simpler, and builds directly on 
what we already have.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20171214/3efa25cb/attachment.html>

More information about the amber-spec-experts mailing list