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 exhaustive;  - 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.

Reply via email to