Yield as contextual keyword (was: Call for bikeshed -- break replacement in expression switch)

Guy Steele guy.steele at oracle.com
Mon May 20 16:33:28 UTC 2019


> On May 20, 2019, at 12:16 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
> 
>> But I now think that this argument is weak, because I believe it is in fact unlikely that there will be a large number of other statement types that we will want to turn into expressions.
>> 
>> 	* Yes, we may want block expressions.
>> 	* We would want `if`-statement expressions _except_ that we already have the ternary operator ? :, so I don’t really think there is a pressing need.
>> 	* As a Common Lisp programmer, I can see the value of having a `for` loop produce a value.  But I very much doubt that Joe Java-programmer wants that.
>> 	* And if we don’t want values from `for` loops, I doubt there will be much demand for values from `while` loops or `try` statements.
> 
> While I agree about if / for / while, I’m not completely convinced on `try`; the notion of “produce a value or throw” is a common one, and has all the same advantages over a try statement that a switch expression has over a switch statement — that initialization of variables with side-effectful statements is messier and more error-prone than with expressions.  So, for example, the not-so-uncommon idiom: 
> 
>    static final Foo foo;
>    static { 
>        try {
>            foo = new Foo();
>       }
>       catch (FooException fe) {
>           throw new OtherKindOfException(fe);
>       }
>    }
> 
> leaves, well, room for improvement.  Let’s just register that as something we might want to do someday.

Sure, I concede that I was hasty on this one.

> Another form of expression that might have statements in it is some sort of “let” or “with” expression; it is not uncommon enough to have to execute statements to produce a result:
> 
>    Foo f = new Foo();
>    f.setBar(1);
>    return f;
> 
> which similarly would like to be replaced with an expression.  (let’s not design this here, the point is that this is a road we might well want to walk again some day.)

But that’s easily handled by a block expression.  (Java doesn’t already have a `let` or `with` statement precisely because being able to intersperse declarations with statements in a block does that job quite nicely.)


<bikeshed level=“hyper">

So, for fun, I’m going to taste-test these two excellent examples.  Offhand I see no problem with using the `try` keyword in the middle of an expression, just as we did for `switch`, so:

   static final Foo = try {
           break: new Foo();
      }
      catch (FooException fe) {
          throw new OtherKindOfException(fe);
      };

Perhaps more interesting is returning a default value if a FooException occurs—and maybe we can tighten up the main body by using parentheses:

   static final Foo = try (new Foo())
      catch (FooException fe) {
          break: myDefaultFoo;
      };

and maybe even the `catch` body could be tightened up in the same way:

   static final Foo = try (new Foo()) catch (FooException fe) (myDefaultFoo);

As for the other one:

	({ Foo f = new Foo(); f.setBar(1); f })

looks pretty good me.

None of this is to make an actual proposal that this is best or even good, or that we should do it soon; it’s just to see whether there is something plausible available.

</bikeshed>


More information about the amber-spec-experts mailing list