Switch expressions -- some revisions
Brian Goetz
brian.goetz at oracle.com
Thu Dec 14 22:45:58 UTC 2017
While we cannot always select the target type early, we always know
whether the switch is in an value-bearing (expression) or void
(statement) context. So we can require that all breaks have the
appropriate polarity, and properly validate whether -> is allowed, even
before we know the types.
You could say that the arms themselves have a type, but that's mostly
only useful for type-checking that the arms are consistent with the type
of the switch.
There are still differences between the two forms (such as
exhaustiveness requirements), so calling a statement switch a "void
expression switch" might still be a bit of a stretch, but it may help as
a way of understanding what's going on if you don't look too closely.
On 12/14/2017 5:28 PM, Ali Ebrahimi wrote:
> Hi Brain,
> +1;
>
> Can we say existing switch construct arms results void value (by
> break) but we want to enhance that to results non-void values (using
> break by value).
> In other word, the result type of existing switch construct is void
> but now based on target type of switch construct can be non-void and
> it is required to break by value.
>
> Note:I'm deliberately avoiding 'return' term and use result term
> instead here.
>
>
>
> On Fri, Dec 15, 2017 at 12:52 AM, Brian Goetz <brian.goetz at oracle.com
> <mailto:brian.goetz at oracle.com>> wrote:
>
>
> After reviewing the feedback on the proposal for switch
> expressions, and a bit of going back to the drawing board, I have
> some proposed changes to the plan outlined in the JEP.
>
>
> 1. Throw expressions. While throw expressions are a reasonable
> feature, many expressed concern that if permitted too broadly
> (such as in method invocation context), they would encourage
> "tricky" code for little incremental expressiveness. The real
> need here is for arms of expression switches to be able to throw
> when an unexpected state is encountered; secondarily it may be
> useful allow a value-bearing lambda to unconditionally throw as
> well. But extending this to &&, ||, assignment, and method
> invocation context seems like asking for trouble. So we'll narrow
> the treatment here, allowing throw on the RHS of a switch
> expression ARM, and possibly also the RHS of a lambda. (This
> doesn't close any doors on making `throw` an expression later, if
> desired.)
>
>
> 2. Local return from switch. In the proposal, we borrowed the
> convention from lambda to use "return" for nonlocal return, mostly
> on the theory of "follow the arrow". But this is pretty
> uncomfortable, made worse by several factors: a) despite the
> syntactic similarity, we don't follow exactly the same rules for
> case arms of expression switches as for lambdas (such as treatment
> of captured vars), and b) when refactoring from statement switch
> to expression switch or vice versa, there's a danger that an
> existing "return" could silently swap between nonlocal and local
> return semantics.
>
> 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 challenge is ambiguity; this could be interpreted as a
> nonlocal break out of an enclosing loop whose label is `x`. But
> then we realized that if `x` is both a variable and a label, we
> can just reject this, and tell the user to rename one or the
> other; since alpha-renaming the label is always source- and
> binary-compatible, the user has at least one (if not two)
> reasonable choices to get out of this problem.
>
> The benefit here is that now "break" means basically the same
> thing in an expression switch as it does in a statement switch; it
> terminates evaluation of the switch, providing a value if one is
> needed. Having addressed the ambiguity problem, I think this is a
> slam-dunk, as it aligns expression switch and statement switch
> quite a bit (same capture rules, same control flow statements.) We
> can also, if we like, support "break" for local return in lambdas
> (we should have done this in 8), to align the two.
>
>
> 3. (Optional.) There's room to take (2) farther if we want,
> which is to complete the transformation by eliminating the fake
> "block expression" in favor of something more like existing
> switch. The idea would be to borrow from statement switches, and
> rewrite the above example as (note where we use colon vs arrow):
>
> int y = switch(abs(x)) {
> case 1 -> 1;
> case 2 -> 2;
> case 3 -> 3;
> default:
> println("more than 3");
> break x;
> };
>
> So in this context, then "case L -> e" in an expression switch is
> just sugar for "case L: break e". As with lambdas, I expect the
> statements+break form to be pretty rare, but we still need to have
> a way to do it (not all objects can be created in a single
> expression without resorting to stupid tricks.)
>
> A good way to think about this is that this is leaving statement
> switch completely alone, and then expression switch "extends"
> statement switch, adding the nice arrow shorthand and the
> exhaustiveness analysis. The downside is that expression switch
> is even more "infected" by existing switch semantics, but after
> thinking about it for a while, this doesn't bother me. (It's more
> uniform, plus its considerably harder to make the "accidental
> fallthrough" mistake in an expression switch than a statement switch.)
>
> I expect this proposal will be a little more controversial than
> (2) -- mostly because some are probably holding out hope that we'd
> radically rework existing switch -- but it has the major advantage
> of further building on existing switch, and also refrains from
> introducing a similar but different kind of fake block expression.
> Overall this is is more of a "build on what's there" solution,
> rather than "add something new in the gap."
>
>
>
>
>
> --
>
> Best Regards,
> Ali Ebrahimi
More information about the amber-spec-observers
mailing list