anonymous records as an implementation for tuples in Java
Brian Goetz
brian.goetz at oracle.com
Wed Dec 11 17:58:55 UTC 2024
This suffers from the same problem as C# anonymous classes -- while you
could theoretically get nominal (x.s) access to the components within
the class declaring the anonymous class, you have no chance of stable
linkage across classes, and this is a huge limitation. Again, it
reduces the value down to something purely syntactic, and not much at that.
(We explored enabling this by redefining the type of an anonymous class
creation expression to be sharper -- Foo$1 instead of Object in this
case -- but the use was so limited, and it merely teased people into
thinking it was more than it was.)
On 12/11/2024 12:50 PM, Anatoly Kupriyanov wrote:
> 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:
>>>
>>> vartuple=(intid: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/adf676d4/attachment-0001.htm>
More information about the amber-dev
mailing list