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