Yielding blocks
Tagir Valeev
amaembo at gmail.com
Sat Mar 5 02:38:27 UTC 2022
For the record, I suggested a similar enhancement two years ago:
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-March/002046.html
The difference is that I think that explicit prefix, like `do { ... }`
would be better. In particular, it helps to disambiguate between array
initializer and block expression..
With best regards,
Tagir Valeev
On Sat, Mar 5, 2022 at 12:36 AM Brian Goetz <brian.goetz at oracle.com> wrote:
>
> The following was received on the -comments list.
>
> Summary: "Can we please have block expressions, you're almost there with the yielding block in switch expressions."
>
> My observations: There was some discussion around the time we did switch expressions about whether we wanted a general-purpose block expression; it was certainly clear that we were inventing a limited form of block expression, and the worst thing about what we did back then was open the door to block expressions a bit, raising the inevitable questions about "why not just throw open the door". While I can imagine wanting to open up on this at some point in the future, and am sympathetic to the notion that we want to express some things as expressions that currently require statements, I'm still not particularly motivated to throw open this door at this time.
>
>
> -------- Forwarded Message --------
> Subject: Yielding blocks
> Date: Fri, 4 Mar 2022 01:22:19 +0200
> From: Dimitris Paltatzidis <dcrystalmails at gmail.com>
> To: amber-spec-comments at openjdk.java.net
>
>
> Methods, ignoring their arguments, form 2 categories:
> 1. Those that do not return a value (void).
> 2. Those that do.
>
> Now, stripping away their signature, we get anonymous methods. Java supports
> category 1, "blocks". They can be local, instance initializers or even
> static.
> On the other end, category 2 is missing. Consider the examples below of
> trying
> to initialize a local variable, with a complex computation.
>
> A. (Verbose and garbage producing)
> Type a = ((Supplier<Type>) () -> {
> .
> .
> return .. ;
> }).get();
>
> B. (The hack, hard to reason)
> Type a = switch (0) {
> default -> {
> .
> .
> yield .. ;
> }
> };
>
> C. (Does not exist)
> Type a = {
> .
> .
> yield .. ;
> }
>
> All of them are equal in power, yet C is compact and readable. Of course, no
> one will resort to A or B, instead they will compute in the same block as
> the
> variable in question (a). Unfortunately, that has a few drawbacks:
> 1. Pollution of the block with temporary variables that won't be needed
> further
> down the line, and at the same time, prohibiting the usage of the same
> name,
> especially if they were final.
> 2. Hard to reason where statements and computations start and end, without
> resorting to comments.
>
> Now, with limited power we can have:
>
> D. (Legal)
> Type a; {
> .
> .
> a = .. ;
> }
>
> Actually D has fewer characters than C, for small enough variable names. It
> also
> solves the pollution problems stated above. But, as already mentioned, it
> lacks
> in power. We can't use it in places where only 1 statement is permitted,
> like
> computing the parameter of a method inside its parenthesis.
>
> With C, we can even initialize instance variables (or static) that require
> multiple statements, without resorting to an instance initializer block.
> Basically, computing a value ad-hoc that fits everywhere.
>
> The block right of the arrow -> of a switch case is basically it. It just
> needs
> a promotion to stand on its own.
More information about the amber-spec-observers
mailing list