New JEP: Switch Expressions for the Java Language

Remi Forax forax at univ-mlv.fr
Sun Dec 10 18:59:36 UTC 2017


> De: "Brian Goetz" <brian.goetz at oracle.com>
> À: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Envoyé: Dimanche 10 Décembre 2017 18:56:51
> Objet: Re: New JEP: Switch Expressions for the Java Language

> Here’s another way of looking at expression switch. This is a
> translation-centric view, but may be useful both as a mental model and as a
> specification approach as well.

> If I have an expression switch:

> T y = switch (x) {
> case A -> e;
> case B -> f;
> }

> We could implement by desugaring the switch into the invocation of a synthetic
> method:

> T y = m$switch(x, a, b, ...)

> where a, b, ... are locals mentioned in e and f. And m$switch() is:
> - replace "case L -> e" with "case L: return e"
> - replace case L -> block with "case L: block"**
> - m$switch() is declared to throw any checked exceptions thrown by switch arms.

> ** This is exploiting the otherwise-unfortunate pun between local return and
> nonlocal return.

I prefer to think that instead of a call to a synthetic method, an invokedynamic that also takes a and b as argument is used. 
With an invokedynamic, you can reorganize the different cases (if the semantics of the expression switch allows that, and i believe it should) dynamically based on the dynamic values of x, something very similar to an inlining cache, which means in term of performance model that a virtual call and a call through an expression switch can be equivalent. 
Anyway, it changes nothing to the current discussion. 

> Where does this leave us?

> - Can't do nonlocal return out of an expression switch. That's good -- that's
> what we wanted anyway.
> - Can't reference mutable locals. That seems OK, but see below.
> - Fallthrough in expression switches (other than OR patterns) is cleverly
> prohibited by the syntax of switch expressions.

> This mental model leaves us pretty close to where we thought we wanted to land
> anyway (whether or not we actually translate like this.)

> Note that the “effectively final” constraint is stronger than it needs to be to
> support this model. The reason that captured locals of even stack-confined
> lambdas need to be effectively final is that the capture point and the
> invocation point of the lambda might be different, and so there would be two
> credible answers for what the following program could print:

> int x = 3;
> Runnable r = () -> println(x);

> x = 4;
> r.run();

> You could argue for either 3 or 4 here, so to eliminate the potential for
> confusion (among other reasons) we say “no non-effectively-final captures”.
> But, for an expression switch desugared as above, the capture point and
> invocation point are guaranteed to be the same. So we could easily say that its
> OK to reference (but not mutate) mutable locals in a switch expression, and it
> would be consistent with the model given.

I agree. The capture point and invocation point are the same if you do that in the correct order, you have to evaluate the expression of the switch before capturing the variables. 

Otherwise doing a side effect inside of the switch, 
int a = 3; 
switch(f(a = 4)) { 
case L -> a; 
} 
and you're in trouble. 

> Note that “consistency” offers us no guidance here; in one approach we’re
> consistent with lambdas but inconsistent with, say, conditional expressions
> (which can reference and even mutate mutable locals.)

Your talking about semantics consistency in general, it's not what a regular user see, the "syntax to semantics" consistency is more important, 
if the syntax use an arrow, then the semantics should be the same with the other(s) construct(s) that are using an arrow. 

> So, candidates for what happens here:
> - like conditional expression — anything goes, locals can be mutated
> - can read locals, but can’t write them — a reasonable position, but unlike
> anything else so far
> - like lambdas - effectively final locals only.

yes, 
and there are several arguments against 2, as you wrote, "it's unlike anything else", it forces users to think where the capture occurs exactly (my example above) and it's not "syntax to semantics" consistent but this can be fixed by not using the arrow symbol. 

Rémi 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20171210/c9925f53/attachment-0001.html>


More information about the amber-spec-experts mailing list