anonymous records as an implementation for tuples in Java

Anatoly Kupriyanov kan.izh at gmail.com
Wed Dec 11 17:50:32 UTC 2024


Agree with Brian, good point. Does not fit Java spirit, especially nominal
stuff. And imho makes code harder to understand and maintain.

However, I could suggest a compromise to enhance anonymous ad-hoc classes
we have currently:

var x = new Object() {
  final int i = 5;
  final String s = "hi";
};
println(x.s);

If this could be slightly reduced with records, it would be nice.
These anonymous types are naturally scoped inside method bodies and could
not pollute domains/etc.

But I am afraid that it does not fit the use-cases which Red is after.


On Wed, 11 Dec 2024 at 17:27, Brian Goetz <brian.goetz at oracle.com> wrote:

> I had thought my reminder in the last reply would be sufficient, but
> again: this is not the Java language design list, and "why don't you just"
> proposals like this just distract us from doing what we've actually
> prioritized.
>
> In the 30 seconds I could spare to look at your idea, it seems to have all
> the same problems as the C# anonymous class feature.
>
> As a side exercise, I invite you to ponder where $TString-int lives, when
> classes in two separate domains both use (String, int) and want to call
> each other, and what could go wrong there.  (But not on this list.)
>
>
> On 12/11/2024 11:59 AM, Red IO wrote:
>
> As tuples can be implemented entirely as synthetic sugar I don't see the
> problem. Simply desugar all denotations of the tuple type to a structurally
> named type similar to arrays. Then create 1 record definition for each used
> type. (which I guess is at some point done for arrays)
> Example:
> (String, int) foo() {
> return ("hi", 42);
> }
> void bar((String, int) tup) {
> System.out.println(tup.0 + tup.1);
> }
>
> var x = foo();
> bar(x);
>
>
> Becomes:
>
> public record $Tjava_lang_String-int(String e0, int e1) extends Tuple {}
>
> $Tjava_lang_String-int foo() {
> return new $Tjava_lang_String-int("hi", 42);
> }
>
> void bar($Tjava_lang_String-int tup) {
>
> System.out.println(tup.e0() + tup.e1()) ;
>
> }
>
>
> var x = foo();
> bar(x);
>
>
> This is completely possible with preprocessing alone. Syntax, descriptor
> format and named vs unnamed elements are details not worth the initial
> discussion.
>
> I think tuples are great and require no fundamentally new features to
> become part of the language.
>
>
> Great regards
>
> RedIODev
>
> On Wed, Dec 11, 2024, 17:23 Brian Goetz <brian.goetz at oracle.com> wrote:
>
>> Yes, this is one of those ideas that sounds good for the first few
>> minutes.  (C# has explored something similar with what they call "anonymous
>> classes", which turned out to be mostly disappointing.)
>>
>> The problem is _linkage_.  It's easy to write out the creation expression:
>>
>>     var tuple = (int id: 10, String name: "foo")
>>
>> So now: what's the type of `tuple`?  What can I assign it to?  How do I
>> extract the members?  How do I write a method that accepts a tuple of (int
>> id, String name)?  What if someone passes it a tuple of (int x, String s)?
>> What does equals and hashCode do on these things?  These things have many
>> potential answers, but none of them are very satisfying.
>>
>> If you're going to create a tuple, presumably someone wants to consume
>> it, store it somewhere, extract its components.  C#'s answer was that you
>> can only do so _within a compilation unit_ (effectively, within the same
>> class) because there was no guarantee that one classes { x: 1, y: 2 } was
>> interoperable with another.
>>
>> Linkage in Java is nominal; when you call a method `m("foo")`, the caller
>> and declaration have to agree on the types, and the method descriptor (in
>> this case, `(Ljava/lang;String;)V`) is recorded in the classfile.  if you
>> want to be able to pass a tuple to a method, we have to record something,
>> and that means either inventing a whole new structural type system to
>> ensure that tuples of the wrong type don't get exchanged, or erasing
>> everything to some "Tuple" class (in which case you lose names and likely
>> types of components.)
>>
>> DISCLAIMER: this is not meant to be a canonical explanation of why we
>> can't have it.  It is literally the first 30 seconds of stuff off the top
>> of my head about why this is more complicated, from the perspective of how
>> the language holds together, than it looks.
>>
>> Essentially, this doesn't really give you the expressive power people
>> want from tuples; what it gives you is a convenient syntactic shorthand for
>> packing the elements into a blob.  Which makes it a fairly weak feature,
>> and one where, once we had it, people would immediately see its weaknesses
>> and then want more.  So it is not any kind of shortcut; it is mostly
>> convincing ourselves that concise creation syntax is the only important
>> thing we get from tuples.  But I don't think that's a good idea.
>>
>> I would put this problem in the same bucket as "collection literals" --
>> optimized syntactic forms for common structural shapes such as lists.  This
>> is on our radar but there are a number of higher-priority things ahead of
>> it, so we won't be talking about it for a while.
>>
>>
>>
>>
>> On 12/11/2024 10:58 AM, david Grajales wrote:
>>
>> I've noticed that the topic of tuples in Java has come up recently, and I
>> wanted to take this opportunity to show an idea regarding the use of *"anonymous"
>> records* as a potential implementation for tuples.
>>
>> The idea would be to create *ad-hoc records* on the fly for short lived
>> methods, which don’t have a formal name but are defined by their
>> components. For example, imagine something like this:
>>
>> var tuple = (int id: 10, String name: "name");
>>
>> This would allow us to create simple, unnamed records with specified
>> fields for quick, on-the-fly usage. Accessing values from the tuple could
>> then work like this:
>>
>> var myTupleId = tuple.id
>> <https://urldefense.com/v3/__http://tuple.id__;!!ACWV5N9M2RV99hQ!JWvS3-XRXfU_BDrdY-5L5h1ddl_PStJP3vNDQtkLvrxFIdBwPvzjEW-LMmG4r8MykbGgC-Y4e8oBmPElPpwijXdqZiO2$>
>> ()
>>
>> for passing them as arguments to methods it could be something like this.
>>
>> void foo(Tuple<Integer, String> tuple){}
>>
>> The idea is that, as records are just classes with special constraints to
>> force invariants, tuples could be records with special constraints, for
>> example as they would be meant to be created on the fly for pin point
>> needs, they should not have validation in the constructor or overriding of
>> getters, but they would still get automatic equals(), hashCode(), and
>> toString() methods.
>>
>>
>> I don't know how problematic or bad this approach would be if there were
>> plans to ever introduce construct tuples to Java.
>>
>> best regards.
>>
>>
>>
>

-- 
WBR, Anatoly.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20241211/f23af282/attachment.htm>


More information about the amber-dev mailing list