------------------------------------------------------------------------
*De: *"Brian Goetz" <[email protected]>
*À: *"Remi Forax" <[email protected]>
*Cc: *"amber-spec-experts" <[email protected]>
*Envoyé: *Jeudi 13 Août 2020 15:42:40
*Objet: *Re: A peek at the roadmap for pattern matching and more
We want a destructor, a destructor is a method that returns a
list of values the same way a constructor takes a list of
parameters.
The way to represent that list of value is to use a record.
Yes, already been down that road, I did an entire sketch of this
feature where we expose “anonymous records.” It felt really cool
— for about five minutes. The conclusion of this exercise was
that in this case, records are better as a _translation mechanism_
than a surface syntax.
first why ? and second, my experience is the opposite, the more there
is a difference between Java the language and the translation strategy
the more it will bite you with corner cases.
So yes, the way to represent it is a record, but in the class
file, not the language.
So we can already write a de-constructor with the current
version of Java,
As you figured out, if you cast a deconstructor as a method with a
special name, you say goodbye to deconstructor overloading. And
if you do make it magically overloadable, then it's magic,
It's not magic, it's a translation strategy like the same way with
bridges, you can have methods with the same name and different return
types.
and you’ve lost all the benefit off pretending its a method. You
just moved the complexity around. And again here comes that glass
half empty feeling: “Why can I only do it with this method?”. Much
better to recognize that deconstruction is a fundamental operation
on objects, just like construction — because it is.
But constructors are plain methods with some special bells and
whistles (funny names, funny rules for the initialization of this and
final fields, etc).
Having a deconstructor being a method with several overloads doesn't
strike me as very magic compared to a constructor.
And you can not have several overloaded methods with different return
types because Java like C doesn't force you to specify the return type
of a method call. So unlike with a pattern where you provide the type,
you don't provide the return type when you do a method call.
i should wuth by example a method minMax that returns both the
minimum and the maximum of an array
public static (int min, int max) minMax(int[] array) {
Nope. Not going there. I went down this road too, but
multiple-return is another one of those “tease” features that
looks cool but very quickly looks like glass 80% empty. More fake
tuples for which the user will not thank us. And, to the extent
we pick _this particular_ tuple syntax, the reaction is “well then
WTF did you do records for?”
Records are the underlying type used by the tuple syntax.
The tuple syntax is as its name suggest, just a syntax. From the
semantics POV, it's an anonymous record, thus, not a structural type.
You may use a record instead of an anonymous record, if you want to
reuse the same record for multiple deconstructor, if i have several
classes representing rectangular shape, i may want them to share the
same record.
It's really very similar to the difference between a method reference
and a lambda or a classical class and an anonymous class. A record is
explicitly named, it can have annotations, it can be serializable,
implements interfaces, have it's own toString() etc. An anonymous
record is the anonymous version of a record, where you don't care
about the name or resource sharing (on record per deconstructor).
Having records _and_ structural tuples would be silly. We’ve
made our choice: Java’s tuples are nominal.
But the syntax you are proposing for deconstruction is using the
syntax of a _structural tuples_ . Here the glass is half empty,
because why the deconstructor can have that feature and not any
methods given that at the end a de-constructor is desugared as a
method that return a record. As i said in my original mail. I agree
with you that we don't want a _structural tuples_, but it's not, it's
an anonymous record and restricted them only to deconstructor does not
make make a lot of sens.
I's like saying look this shinny anonymous record, deconstructor can
use them but not regular methods.
Worse, it only addresses the simplest of patterns — deconstructors
— because they are inherently total. When you get to conditional
patterns (Optional.of(var x)), you want to wrap that record in
something like an optional. If the return value is fake, now you
have to deal with the interaction of trade tuples and generics.
No thank you.
I don't see the issue here, where is the problem with the following code ?
Optional<(int x, int y)> deconstructor() {
return Optional.of( (this.x, this.y) );
}
Maybe users will find the syntax weird ? But it's like any new feature ?
I believe you are thinking that the type (int x, int y) is a tuple
while technically it's an anonymous record, so from the type system
POV it acts as a record, i.e. a nominal class.
Believe me, I’ve been down ALL of these roads.
the compiler will generate a synthetic record, so the
generated code is equivalent to
The synthetic record part is the part I liked, and kept.
There’s room for an “anonymous tuple” feature someday, maybe, but
we don’t need it now.
I'm not suggesting to introduce an anonymous tuple, as you said above,
we have decided to use record instead, a nominal type.
I'm suggesting to introduce the concept of anonymous record, which is
what the synthetic record is, because i see no point to restrict it
only to deconstructors.
I’m willing to consider the “record conversion” when we get to
collection literals, but not now.
To represent the couple key/value i suppose.
I don't disagree, but i don't think it's wise to introduce the idea of
a synthetic record without the notion of anonymous record, but we
don't need a synthetic record for deconstructors, it's nice to have
but not an essential part of the design.
Rémi