Call for bikeshed -- break replacement in expression switch

John Rose john.r.rose at oracle.com
Fri May 17 01:15:36 UTC 2019


On May 16, 2019, at 2:43 PM, Alex Buckley <alex.buckley at oracle.com> wrote:
> 
> If you're proposing to disallow a cast expression or a parenthesized expression after a `yield` token, then I think that's not right. The parsing of a `(` token has triggered potentially unbounded lookahead for some time [1][2], and everything worked out, so I don't see why the language should disallow any of John's examples:
> 
> yield (String)("answer is "+x);
> yield ("answer is "+x).trim();
> yield new String[]{ "answer is "+x }[0];
> yield Arrays.asList("answer is "+x).get(0);
> yield false ? 0 : ("answer is "+x).trim();

Here's what's tricky:  If there is a method called "yield"
in scope, then one of those examples is a valid method
call expression statement.

import static MyFavYielder.yield;
class Client extends MaybeHasYieldMethod {
void m(int x) {
var res = switch (x) {
 case 42 -> {
  yield ("answer is "+x).trim();
 }
default -> -1;
}}

Here's one way to slice it (very thin):

The name "yield" is placed in scope in "->"
blocks as if it were an inherited or imported
static method.  It acts like an arity-1
signature-poly method returning void.
When "yield" is followed by a paren,
an appeal to this method, and any
other ambient methods named "yield"
is made, and overloading and ambiguity
analysis is done.  If after all the special
sig-poly method is matched, then the
compiler edits the statement into a
control flow construct.

(This is circular:  A control flow construct
affects ambient DA/DU rules which might
also indirectly affect types IIRC.  So the type
of the yield call maybe could circularly depend
on the surrounding control flow.)

If the built-in "yield" quasi-method conflicts
with a real "yield" method that is in scope
and matches, the we report an ambiguity
to the user.   (Ambiguity?  Ya think??)
The user has to fix it by using a fully
qualified call to the intended yield or
some similar dodge.  If the yield statement
is desired, at worst case the user makes
a temporary variable, and yields *that*.

This trickiness does tend to support a
less ambiguous syntax, such as "yield -> x;"
or (per Doug) "yield ^x;".

— John

P.S. I find "yield -> x" charming partly because the
arrow seems to have additional possibilities:

if (foo) {
   yield -> {  var x = waitASec();  var y = OK; yield -> f(x, OK); };
}

instead of:

if (foo) {
   var x = waitASec();  var y = OK; yield -> f(x, OK);
}




More information about the amber-spec-experts mailing list