groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jochen Theodorou <blackd...@gmx.org>
Subject Re: [GEP] Switch expressions syntax from Java 11 or 12 (perhaps)
Date Thu, 01 Mar 2018 23:57:16 GMT
On 01.03.2018 16:39, Jesper Steen Møller wrote:
[...]
> |int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case 
> TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; };|
> 
> with
> 
> |case LABEL -> expression;|
> 
> essentially sugar for
> 
> |case LABEL: break expression;|

to make this straight.

> int result = switch (s) {
>     case "Foo":
>         break 1;
>     case "Bar":
>         break 2;
>     default:
>         System.out.println("Neither Foo nor Bar, hmmm...");
>         break 3;
> }

is the long form of

> int result = switch (s) {
>     case "Foo" ->  1;
>     case "Bar" ->  2;
>     default:
>         System.out.println("Neither Foo nor Bar, hmmm...");
>         break 3;
> }

The default here has no shorter version, because they are using a 
statement and need to return something in the expression. I understood 
the proposal, that both forms are valid and can be mixed.

There is a few things I dislike...and most of all it is the break 
command here.

> int accumulator = 0
> LOOP: for (T element : someList) {
>   accumulator += switch (element.type) {
>     case PLUS_ONE -> +1;
>     case MINUS_ONE -> -1;
>     case ERROR:
>       break LOOP;
>     case default -> 0
>   }
> }

with the idea that element.type is an enum... But my problem is with 
break LOOP. Is LOOP the label LOOP, or is it a constant/variable?

If they need the break only to break out of the switch, then why not 
capitalize on lambdas?

> int accumulator = 0
> LOOP: for (T element : someList) {
>   accumulator += switch (element.type) {
>     case PLUS_ONE -> +1;
>     case MINUS_ONE -> -1;
>     case ERROR -> {break LOOP;}
>     case default -> 0
>   }
> }

This would be much more aligned with what Java has, then you would 
naturally use return if you are required to use statements. Plus it 
would align more with what is in JEP-305 with for example "case Integer 
i -> i+1". I would not even support the column version for a switch 
expression.

And then of course there is the basic problem: you have to have a single 
expression. Not many people are actually like using switch-case, I do, 
but rarely this is for me in the break expression style as described. 
For me this whole construct makes no sense without JEP-305 and for that 
JEP you do not need some of the variants described at all. Let us not 
forget that the switch-object is limited to quasi constants such as 
strings, enum values and integers. They do not have the isCase 
construct, thus no variant to do an equals based check. Even with 
JEP-305, this is not changed. In theory you could do something like this 
in Java:

>   accumulator += switch-case (element.type, 
>     new Case(PLUS_ONE, -> +1),
>     new Case(MINUS_ONE, -> -1),
>     new Case(-> 0));

Then switch-case can be a generic function, that checks the Case objects 
for the supplied matched and on equality executed the provided lambda. 
This variant would realize the break expression version and would not 
support labels or return statements (only as part of the lambda). But it 
would be possible to do, even extensible to do more than just that - and 
allow lambdas for the matcher as well.

[...]> Now, this being Groovy, the cases should surely support the extended
> "isCase"-support, as described so well here: 
> http://mrhaki.blogspot.dk/2009/08/groovy-goodness-switch-statement.html
> 
> So, three questions remain:
> 1) Useful or not?

for me not, it is one of the constructs I would not use. And given the 
sentiment against switch-case by many programmers, they would not either.

> 2) This Java compatibility - is it still a thing? I remember a similar 
> proposal a little while back, but this would align better with Java.

IMHO there is still work in that bug report to align better with Java ;) 
For Groovy yes... if they add it to Java, we add it to Groovy... but not 
because it is good or useful, just for compatibility

> 3) This could be implemented using existing AST's if we /_really_/ want 
> to, but it would be clumsy. This AST transformer compatibility - is it 
> still a thing?

Sure it is a thing, but I doubt it can be implemented using the AST. 
switch-case is a statement, and while we have expression-statements 
(expressions as statements) we do not have statements as expressions. 
And I think none of the constructs in the bug would even pass the 
parser. Without parser, no AST.

Meaning to implement this, you have to change the grammar,then you have 
to introduce a new expression type and extend the visitors to support 
it. And finally you may be able to match it to the switch statement, but:

int f(n, m) {
   int res = switch (n) {
     case 0 -> m+1;
     default -> switch(m) {
       case 0 -> f(n-1,1)
       default -> f(n-1, f(n,m-1))
     }
   }
   return res;
}

This will not be easy, because you will need a temporary variable if you 
want to simulate this with the statement form... And frankly not sure it 
is worth it compared to a "real" implementation in the compiler, which 
will not have to use it. Of course you would normally not use 
switch-case for this, it is just an example for a complex expression 
having a nested switch-case-expression.

In summary: I would wait for what the Java guys decide in the end.

bye Jochen

Mime
View raw message