Expression switch - an alternate proposal
Cay Horstmann
cay.horstmann at sjsu.edu
Thu Apr 12 22:57:20 UTC 2018
I am in agreement that
topping = switch (food) {
case BURGER -> KETCHUP;
case SAUSAGE, ASPARAGUS -> MUSTARD;
case ICE_CREAM -> FUDGE;
default -> NOTHING;
}
is good, and that I would be happy to explain it before statement
switch. (Mustard on asparagus, though?)
But the switch from
case BAKED_POTATO -> SOUR_CREAM
to
case BAKED_POTATO:
Toppings t = new Toppings();
t.add(BACON);
t.add(SOUR_CREAM);
t.add(CHEESE);
t.add(BACON); // not a typo
break t;
is a problem.
It is quite different from the equivalent transformation with lambda
expressions:
Callable<TOPPING> task = () -> SOUR_CREAM;
to
Callable<TOPPING> task = () -> {
Toppings t = new Toppings();
t.add(BACON);
t.add(SOUR_CREAM);
t.add(CHEESE);
t.add(BACON); // not a typo
return t;
};
And it requires a new construct, break with value, that has no use
anywhere else (one hopes).
Perhaps you shouldn't allow statements in a switch expression? They
aren't allowed in a ? : expression either.
I also don't understand Rémy's remark that a traditional break inside a
switch expression is disallowed. What rules out
case BAKED_POTATO:
Toppings t = new Toppings();
t.add(SOUR_CREAM);
t.add(CHEESE);
int count = 0;
while (true) {
if (count == 10) break; else count++;
t.add(BACON);
}
break t;
Or more horrifyingly,
case BAKED_POTATO:
Toppings t = new Toppings();
t.add(SOUR_CREAM);
t.add(CHEESE);
int count = 0;
while (true) {
if (count == 10) break t; else count++;
t.add(BACON);
}
Is there a restriction on what can go into the semicolon-separated list
of statements in the case label of an expression switch? I couldn't see
one in the JEP. And if not, what happens if there is a return? A break
without value? A continue?
What about variable declarations? In statement switch, the following is
legal:
switch (foo) {
case 1:
int x = 1;
default:
x = 2;
System.out.println(x);
}
and the following is not:
switch (foo) {
case 1:
int x = 1;
System.out.println(x);
break;
case 2:
int x = 2;
System.out.println(x);
break;
}
It seems that, if variable declarations are allowed in an expression
switch, the rules are going to have to be different :-)
If you shore this up by restricting the statements that can follow a
case label in an expression switch, haven't you implicitly defined a
block expression? In that case, why not make it a general construct?
Cheers,
Cay
Le 12/04/2018 à 05:48, Brian Goetz a écrit :
> I think Remi has it exactly right here: this is a pedagogical blessing
> in disguise -- as long as we can let go our of pre-existing notions of
> how it ought to be taught.
>
> The switch statement is nasty and complicated in multiple ways; surely
> you don't want to teach that first if you have a choice. So start with
> the simplified form of the switch expression:
>
> topping = switch (food) {
> case BURGER -> KETCHUP;
> case SAUSAGE, ASPARAGUS -> MUSTARD;
> case ICE_CREAM -> FUDGE;
> default -> NOTHING;
> }
>
> Students should be able to grasp this immediately; if its one of the
> things on the left, pick the thing on the right. You can get a long way
> with this.
>
> Eventually you will come across a situation where the right-hand side is
> not a simple expression. Then you can teach them the escape hatch for
> adding statements into the mix:
>
> topping = switch (food) {
> case BURGER -> KETCHUP;
> case SAUSAGE, ASPARAGUS -> MUSTARD;
> case ICE_CREAM -> FUDGE;
> case BAKED_POTATO:
> Toppings t = new Toppings();
> t.add(BACON);
> t.add(SOUR_CREAM);
> t.add(CHEESE);
> t.add(BACON); // not a typo
> break t;
> default -> NOTHING;
> }
>
> You can explain that "break" in a switch is like "return" in a method.
> While the "spelling" might seem weird, the concept is not hard.
>
> Now, when you need to, you can teach the switch statement in all its
> glory. They've already seen switching; they've already seen breaking;
> what's left it to explain fallthrough (no way around this) and the lack
> of exhaustiveness.
>
>
> Which is to say:
>
> - New users can probably learn the concepts better by adding them in
> one at a time; first simple expression switches, then adding in break,
> then statement switches.
>
> - Existing users, who have already been through the gauntlet of
> learning fallthrough, will necessarily learn it in the opposite order,
> but they should be able to recognize that break means the same thing it
> always has, so there are still relatively few new concepts here.
>
> This seems like a pretty good pedagogical story either way!
>
>
>
> On 4/12/2018 3:23 AM, Remi Forax wrote:
>> ----- Mail original -----
>>> De: "Cay Horstmann" <cay.horstmann at sjsu.edu>
>>> À: "amber-dev" <amber-dev at openjdk.java.net>
>>> Envoyé: Jeudi 12 Avril 2018 06:50:35
>>> Objet: Re: Expression switch - an alternate proposal
>>> I've thought about this more and in the end decided to speak up. Over
>>> the years, I explained a substantial number of Java features to a very
>>> large number of people, and I generally have a pretty good idea of where
>>> people struggle. Anonymous inner classes, wildcards, constructor
>>> references, the unnamed module, you name it. With all of these features,
>>> I knew I had my work cut out explaining them, but I wasn't too bothered.
>>>
>>> I am bothered by the proposed expression switch syntax.
>>>
>>> When I read these discussions about colons vs. arrows, I fear that they
>>> mask a much bigger issue. I do not think that there is significant
>>> transfer from the existing switch statement to what we want to achieve
>>> with expression switch. The matching part is similar, but the control
>>> flow is not.
>> the control flow of an expression switch is a subset of the control
>> flow of a statement switch because it's an expression.
>>
>>> Maybe I am wrong. If there has been user testing that confirms that
>>> programmers properly transfer their knowledge of statement switch to
>>> expression switch with the "break x" syntax, that's great, and I'll shut
>>> up. In absence of such evidence, I would urge (1) to make expression
>>> switch visibly different from statement switch and (2) have an ironclad
>>> justification for "break x" or abandon it. It has tension with labeled
>>> break and classic break which can be present inside a branch of an
>>> expression switch. Teaching a break/return analogy does not seem any
>>> easier than teaching about block expressions.
>> You can not have a break label (or a continue) inside a switch
>> expression, again it's an expression, it's like ?:, you can have a
>> break label into it.
>>
>> I disagree that teaching block expressions is as easy that teaching
>> break expression, with block expressions, you also have to teach why
>> you can not use it anywhere else in Java.
>> The break expression does not have this issue. BTW, i think it's easy
>> in term of teaching to teach the switch expression first and then to
>> teach the statement switch given that the expression switch semantics
>> is a subset of the statement switch semantics.
>>
>>> Cheers,
>>>
>>> Cay
>>>
>>>
>> Rémi
>>
>>>
>>> Le 10/04/2018 à 13:59, Stephen Colebourne a écrit :
>>>> On 10 April 2018 at 09:02, <forax at univ-mlv.fr> wrote:
>>>>>>> Basically, your proposal is to use -> eveywhere, i think i prefer
>>>>>>> the opposite,
>>>>>>> do not use arrow at all.
>>>> Current Oracle proposal:
>>>> statements = colon
>>>> expression = colon, with arrow for expressions
>>>>
>>>> Alternate proposal:
>>>> statements = colon
>>>> expression = symbol-that-isnt-colon
>>>>
>>>> Remi proposal:
>>>> statements = colon
>>>> expression = colon
>>>>
>>>> If the goal is a unified switch expression, Remi proposal wins. It is
>>>> dead simple and very consistent.
>>>>
>>>>>> This is a reasonable alternative, but I don't think it would be very
>>>>>> popular. I think people will really love being able to write:
>>>>>>
>>>>>> case MONDAY -> 1;
>>>>>> case TUESDAY -> 2;
>>>>>>
>>>>>> and will be sad if we make them write
>>>>>>
>>>>>> case MONDAY: break 1;
>>>>>> case TUESDAY: break 2;
>>>> Meh. Three more characters.
>>>>
>>>> Yet:
>>>> - Avoids the arrow having a conflict of meaning with lambda.
>>>> - No mixed arrows & colons
>>>> - Much more consistent.
>>>> - Minimal change from existing switch.
>>>> - Less to learn.
>>>> Win, win, win.
>>>>
>>>> So while I'd still choose to have a separate symbol for expression and
>>>> statement switches (because of my #1 goal), I'm also pretty fine with
>>>> the Remi proposal (because my #2 goal).
>>>>
>>>> In fact, what the discussion has informed me is that my #1 and #2
>>>> goals are the wrong way around. Getting rid of the mixed arrows and
>>>> colons is now more important to me than understanding the context in a
>>>> large switch.
>>>>
>>>> Stephen
>>>>
>>>
>>> --
>>>
>>> Cay S. Horstmann | http://horstmann.com | mailto:cay at horstmann.com
>
--
Cay S. Horstmann | http://horstmann.com | mailto:cay at horstmann.com
More information about the amber-dev
mailing list