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