Expression switch - an alternate proposal

Remi Forax forax at univ-mlv.fr
Mon Apr 9 11:49:15 UTC 2018


moving to spec-experts as it can interest others.

Hi Stephen,
First, thanks to do a detailed analysis of the rational of your proposal.

I think i agree with you about the fact that the expression switch does need to support fallthrough,
more on that in a folowing email.

I also agree with you that mixing arrows and colons is confusing.

I am not sure it's that important to make a string distinction between the statement switch and the expression switch.
You do not give any element or why you think it's important and in my opinion, it's the kind of things that you think is important when you introduce the feature and tend to be less important if the feature was not new.

Basically, your proposal is to use -> eveywhere, i think i prefer the opposite, do not use arrow at all.
Using arrow in this context is disturbing because it doesn't mean the same things if it's the arrow of the lambda or the arrow inside an expression switch. 

As i know that you love puzzlers, how about ?

  int a = 0;
  switch(x) {
    case 0 -> { a = 3 };
    case 1 -> () -> { a = 3 };
  }
 
or this one
  switch(x) {
    case 0 -> { break 3; }
    case 1 -> () -> { break 3; };
    case 2 -> { return 3; }
    case 3 -> () -> { return 3; };
  } 

the problem is that currently -> means create a new function scope and not creates a new code scope.

So if do not mixing arrows and colons is an important goal and i think it is, i think it's better to not use arrow.
After all, we need the arrow syntax in lambda only to know if (x) is the start of a lambda or a cast, there is no need to have an arrow in the expression switch.

Moreover, do we really need a shorter syntax given that we can use break and a value ?
Here is your example with no arrow and no short syntax,
  
var action = switch (light) {
  case RED:
    log("Red found");
    break "Stop";
  case YELLOW, GREEN: break "Go go go";
  default:
    log("WTF: " + light);
    throw new WtfException("Unexpected color: " + light);
};

and now we can discuss about adding a shorter syntax by making break optional if there is one expression.

Rémi


----- Mail original -----
> De: "Stephen Colebourne" <scolebourne at joda.org>
> À: "amber-dev" <amber-dev at openjdk.java.net>
> Envoyé: Lundi 9 Avril 2018 01:58:03
> Objet: Expression switch - an alternate proposal

> What follows is a set of changes to the current expression switch
> proposal that I believe result in a better outcome.
> 
> The goal is to tackle four specific things (in order):
> 1) The context as to whether it is a statement or expression switch
> (and thus what is or is not allowed) is too remote/subtle
> 2) Mixing arrows and colons is confusing to read
> 3) Blocks that do not have a separate scope
> 4) Fall through by default
> while still keeping the design as a unified switch language feature.
> 
> To tackle #1 and #2, all cases in an expression switch must start with
> arrow -> (and all in statement switch must start with colon :)
> To tackle #3, all blocks in an expression switch must have braces
> To tackle #4, disallow fall through in expression switch (or add a
> fallthrough keyword)
> 
> Here is the impact on some code:
> 
> Current:
> 
> var action = switch (light) {
>   case RED:
>     log("Red found");
>     break "Stop";
>   case YELLOW:
>   case GREEN -> "Go go go";
>   default:
>     log("WTF: " + light);
>     throw new WtfException("Unexpected color: " + light);
> }
> 
> Alternate proposal:
> 
> var action = switch (light) {
>   case RED -> {
>     log("Red found");
>     break "Stop";
>   }
>   case YELLOW, GREEN -> "Go go go";
>   default: -> {
>     log("WTF: " + light);
>     throw new WtfException("Unexpected color: " + light);
>   }
> }
> 
> How is this still a unified switch? By observing that switch can be
> broken down into two distinct phases:
> - matching
> - action
> What makes it unified is that the matching phase is shared. Where
> statement and expression switch differ is in the action phase.
> 
> The unified matching phase includes:
> - target expression to switch on
> - case null
> - constant case clauses
> - pattern matching case clauses
> - default clause
> 
> The action phase of a statement switch is:
> - followed by a colon
> - have non-scoped blocks
> - fall through by default
> - can use return/continue/break
> 
> The action phase of an expression switch is:
> - followed by an arrow
> - have an expression or a block (aka block-expression)
> - cannot fall through
> - cannot use return/continue/break
> 
> By having a unified matching phase and a separate (but consistent)
> action phase in each form, I believe that the overall language feature
> would be much simpler to learn. And importantly, it achieves the goal
> of not deprecating or threatening the existence of the classic
> statement switch.
> 
> All the key differences are in the action phase, which is clearly
> identified by arrow or colon (no remote context). Developers will come
> to associate the rule differences between the two forms with the arrow
> or colon, while the pattern matching knowledge is shared.
> 
> Of course, the matching phase is not completely unified - expression
> switches must be exhaustive, and they may have auto default case
> clauses. (Perhaps the unified matching phase mental model suggests
> that auto default would be better written explicitly, eg. "default
> throw;", which could then apply to both statement and expression. Not
> sure.)
> 
> I hope this alternate proposal is clear. To me, the split between a
> unified matching phase and a consistent but different action phase
> clearly identified in syntax results in much better readability,
> learning and understandability.
> 
> Stephen
> PS. I think there are alternate block expression syntaxes, including
> ones that avoid "break expression", but I've chosen to avoid that
> bikeshed and use the closest one to the current proposal for the
> purpose of this mail


More information about the amber-spec-observers mailing list