Switch expressions -- some revisions
Stephen Colebourne
scolebourne at joda.org
Thu Dec 14 23:57:40 UTC 2017
On 14 December 2017 at 21:22, Brian Goetz <brian.goetz at oracle.com> wrote:
> 1. Throw expressions.
+1
> 2. Local return from switch.
Using `break` is a good move forward. Lambdas represent code that can
be "picked up and moved" for execution elsewhere. As such, they
correspond closely to methods and classes. The `return` keyword makes
sense in this context. But `return` does not make sense when the code
is inline and can't move.
However, the `return` keyword is only one of two syntactic devices
used to indicate "pick up and move". The other is the -> arrow. In
fact, it is the arrow that ultimately defines "pick up and move" with
the `return` a secondary player in syntax terms. (This explanation is
also why lambdas should not be changed to use `break`.)
Given this, and other discussion in this thread, it is clear to me
that using the -> arrow for expression switch would be a bad mistake.
In addition, the analogy of:
`return` for void methods
`return e` for non-void methods
`break` for void switches
`break e` for non-void switches
appeals greatly. Keeping this would be a big win.
If not -> arrow, then what? Well the starting point should just be
`break`. Its only a few characters longer and absolutely
clear/familiar.
int y = switch(abs(x)) {
case 1: break 1;
case 2: break 2;
case 3: break 3;
default:
println("bigger than 3");
break x;
};
Now we really have something that is really close to the existing
statement switch, which is nice.
But this is also its downside. Because in an existing statement switch
the case clauses are not exhaustive, default can go anywhere, and fall
through happens.
Remi has proposed one solution - a different keyword for expression
switch. This isn't a terrible idea, because as he points out, in Java
expressions and statements tend to have different keywords/syntax. But
I can't say I'm a huge fan of this solution, as the relationship
between void (statement) and non-void (expression) switches has a lot
of appeal in pedagogical terms.
My solution would be (unsurprisingly) to build on old switch in a different way.
int y = switch on (abs(x)) {
case 1: break 1;
case 2: break 2;
case 3: break 3;
default:
println("bigger than 3");
break x;
};
switch on (abs(x)) {
case 1: System.out.println("one");
case 2: System.out.println("two");
case 3: System.out.println("three");
default: System.out.println("more than three");
}
(`switch on` used for examplar purposes).
The new form would apply all the new rules:
- cases are ordered
- `case null` comes first
- `default` comes last
- `default` required (implicit if enum)
- no fall through (use old switch form for that)
- `break` not required in statement form, just like void methods
- use of `continue` is an error (labelled continue can be used to
refer to a loop)
- blocks {} can be used but are not required, they are only needed to
control local variable scope
Key takeaway - I now think -> arrow would be a huge syntactic mistake,
as that symbol means something entirely different with lambdas. Its
the more important part of rejecting `return` here.
Stephen
More information about the amber-spec-observers
mailing list