I certainly agree that blocks would need something to prefix them.  I don't necessarily object to the concept, but we have other, higher-leverage activities I'd rather pursue instead right now.

On 3/4/2022 9:38 PM, Tagir Valeev wrote:
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.go...@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<dcrystalma...@gmail.com>
To:amber-spec-comme...@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.

Reply via email to