From xehpuk.dev at gmail.com Sun Dec 1 14:06:06 2024 From: xehpuk.dev at gmail.com (Henrik Wall) Date: Sun, 1 Dec 2024 15:06:06 +0100 Subject: JEP 495: java.io.IO.printf(String format, Object... args) Message-ID: Hey folks, I'd love to write formatted strings to System.out in a concise way. print("".formatted()) feels wrong, because we already have printf(String format, Object... args). Have you considered adding it to java.io.IO? Regards, xehpuk -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Dec 2 20:57:17 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 2 Dec 2024 20:57:17 +0000 Subject: JEP 495: java.io.IO.printf(String format, Object... args) In-Reply-To: References: Message-ID: We are actively trying to minimize what goes into IO, so our approach right now is an aggressive ?if in doubt, leave it out." On Dec 1, 2024, at 9:06 AM, Henrik Wall > wrote: Hey folks, I'd love to write formatted strings to System.out in a concise way. print("".formatted()) feels wrong, because we already have printf(String format, Object... args). Have you considered adding it to java.io.IO? Regards, xehpuk -------------- next part -------------- An HTML attachment was scrubbed... URL: From ella.ananeva at oracle.com Wed Dec 4 01:03:16 2024 From: ella.ananeva at oracle.com (Ella Ananeva) Date: Wed, 4 Dec 2024 01:03:16 +0000 Subject: Flexible constructor bodies: Odd treatment of "return" in lambdas. Message-ID: Hi team, For some reason, compiler rejects ?return? in lambda if it?s declared in the early construction context. But a similar lambda without ?return? is accepted. Is this by design? interface Foo { int get(); } class Test { Test() { Foo lmb = () -> 1; //is okay Foo lmb2 = () -> { return 1; //fails with a compilation error }; super(); Foo lmb3 = () -> { return 1; //is okay }; } } public void main() { new Test(); } Main.java:13: error: 'return' not allowed before explicit constructor invocation return 1; java --version openjdk 24-ea 2025-03-18 OpenJDK Runtime Environment (build 24-ea+24-2960) OpenJDK 64-Bit Server VM (build 24-ea+24-2960, mixed mode, sharing) Thank you, Ella -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Wed Dec 4 01:47:56 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Tue, 3 Dec 2024 19:47:56 -0600 Subject: Flexible constructor bodies: Odd treatment of "return" in lambdas. In-Reply-To: References: Message-ID: On Tue, Dec 3, 2024 at 7:04?PM Ella Ananeva wrote: > For some reason, compiler rejects ?return? in lambda if it?s declared in > the early construction context. > Hi Ella, That is a bug - thanks for finding and reporting it. Filed as JDK-8345438 . -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From vab2048 at gmail.com Thu Dec 5 09:34:37 2024 From: vab2048 at gmail.com (vab2048) Date: Thu, 5 Dec 2024 09:34:37 +0000 Subject: =?utf-8?Q?=E2=80=9CDeriving=E2=80=9D_functionality_for_classes_a?= =?utf-8?Q?nd_pattern_matching_on_LHS_of_assignment=3F?= Message-ID: Hi Amber team, I was wondering about the future of two different features and thought I would just ask the mailing list. The first feature: deriving instances. Haskell allows type declarations to derive instances for certain type classes (Eq, Ord, Enum, Bounded, Show, and Read). Is it possible to get some sort of equivalent for java classes which would allow us to specify to the compiler to auto derive some code. I am thinking about easily auto-generating a toString, equals, hash code etc? We already have a form of this for records, and so bringing it to classes would make a logical next step. The second feature: pattern matching on LHS of assignment. Suppose we have this record type: record Color(byte red, byte green, byte blue) {} and a static factory method ?someFactory? which returns a Color. Are there any plans to allow us to pattern match at the point of assignment like so: Color(byte red, byte green, byte blue) color = someFactory(); This would be a great addition to pattern matching. Regards, Vikram From gavin.bierman at oracle.com Thu Dec 5 11:17:05 2024 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Thu, 5 Dec 2024 11:17:05 +0000 Subject: =?utf-8?B?UmU6IOKAnERlcml2aW5n4oCdIGZ1bmN0aW9uYWxpdHkgZm9yIGNsYXNzZXMg?= =?utf-8?Q?and_pattern_matching_on_LHS_of_assignment=3F?= In-Reply-To: References: Message-ID: I can speak to the second point: Yes, this is very much on our radar. There has been discussion of this on this list I believe (or maybe on the spec-experts list), and it is mentioned in early design documents that you can read on the Amber project page [1]. There are other places that we would like to consider to support patterns, e.g. in the head of lambda expressions and in enhanced for statements. We may well do these all in one go. Thanks for your interest! Gavin [1]: https://openjdk.org/projects/amber/design-notes/patterns/pattern-match-semantics https://openjdk.org/projects/amber/ On 5 Dec 2024, at 09:34, vab2048 wrote: Hi Amber team, I was wondering about the future of two different features and thought I would just ask the mailing list. The first feature: deriving instances. Haskell allows type declarations to derive instances for certain type classes (Eq, Ord, Enum, Bounded, Show, and Read). Is it possible to get some sort of equivalent for java classes which would allow us to specify to the compiler to auto derive some code. I am thinking about easily auto-generating a toString, equals, hash code etc? We already have a form of this for records, and so bringing it to classes would make a logical next step. The second feature: pattern matching on LHS of assignment. Suppose we have this record type: record Color(byte red, byte green, byte blue) {} and a static factory method ?someFactory? which returns a Color. Are there any plans to allow us to pattern match at the point of assignment like so: Color(byte red, byte green, byte blue) color = someFactory(); This would be a great addition to pattern matching. Regards, Vikram -------------- next part -------------- An HTML attachment was scrubbed... URL: From ethan at mccue.dev Thu Dec 5 15:01:12 2024 From: ethan at mccue.dev (Ethan McCue) Date: Fri, 6 Dec 2024 00:01:12 +0900 Subject: =?UTF-8?Q?Re=3A_=E2=80=9CDeriving=E2=80=9D_functionality_for_classes_and_pat?= =?UTF-8?Q?tern_matching_on_LHS_of_assignment=3F?= In-Reply-To: References: Message-ID: (nonauthoritative opinion) For the first point: While it has its downsides, that capability already exists in the form of code generating annotation processors. I.E. it is possible to have @Ordered public record Hill(int heightAboveSeaLevel) implements HillComparable { } Generate interface HillComparable extends Comparable { @Override default int compareTo(@NotNull Hill o) { return Comparator .comparingInt(Hill::heightAboveSeaLevel) .compare(this, o); } } The problem is that all such code generators - if they were built into the language - would have restrictions on the contexts in which they are applicable. Fundamentally records can only have toString, equals, and hashCode derived for them because by virtue of being a record the language knows that it is just a thin data carrier. It is much more dubious to do something similar for regular classes. On Thu, Dec 5, 2024 at 9:02?PM Gavin Bierman wrote: > I can speak to the second point: Yes, this is very much on our radar. > There has been discussion of this on this list I believe (or maybe on the > spec-experts list), and it is mentioned in early design documents that you > can read on the Amber project page [1]. > > There are other places that we would like to consider to support patterns, > e.g. in the head of lambda expressions and in enhanced for statements. We > may well do these all in one go. > > Thanks for your interest! > Gavin > > [1]: > https://openjdk.org/projects/amber/design-notes/patterns/pattern-match-semantics > https://openjdk.org/projects/amber/ > > > On 5 Dec 2024, at 09:34, vab2048 wrote: > > Hi Amber team, > > I was wondering about the future of two different features and thought I > would just ask the mailing list. > > The first feature: deriving instances. > > Haskell allows type declarations to derive instances for certain type > classes (Eq, Ord, Enum, Bounded, Show, and Read). > > Is it possible to get some sort of equivalent for java classes which would > allow us to specify to the compiler to auto derive some code. I am thinking > about easily auto-generating a toString, equals, hash code etc? We already > have a form of this for records, and so bringing it to classes would make a > logical next step. > > The second feature: pattern matching on LHS of assignment. > > Suppose we have this record type: > > record Color(byte red, byte green, byte blue) {} > > and a static factory method ?someFactory? which returns a Color. > > Are there any plans to allow us to pattern match at the point of > assignment like so: > > Color(byte red, byte green, byte blue) color = someFactory(); > > This would be a great addition to pattern matching. > > > Regards, > > Vikram > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu Dec 5 15:15:46 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 5 Dec 2024 10:15:46 -0500 Subject: =?UTF-8?Q?Re=3A_=E2=80=9CDeriving=E2=80=9D_functionality_for_classe?= =?UTF-8?Q?s_and_pattern_matching_on_LHS_of_assignment=3F?= In-Reply-To: References: Message-ID: <4d03fa54-f8c7-4315-8c07-8d21009c6ddd@oracle.com> On 12/5/2024 4:34 AM, vab2048 wrote: > Hi Amber team, > > I was wondering about the future of two different features and thought I would just ask the mailing list. > > The first feature: deriving instances. > > Haskell allows type declarations to derive instances for certain type classes (Eq, Ord, Enum, Bounded, Show, and Read). > > Is it possible to get some sort of equivalent for java classes which would allow us to specify to the compiler to auto derive some code. I am thinking about easily auto-generating a toString, equals, hash code etc? We already have a form of this for records, and so bringing it to classes would make a logical next step. The strict equivalent of this is records: in Haskell, you don't get any control over how to derive type classes such as Eq and Show, and similarly for records: the one the compiler gives uses all the state.? So in some sense, mission accomplished.? But that's not really what you're asking.? What you're asking is for an _arbitrary class_ -- not just a `data` type -- to be able to get these somehow. We did several extensive explorations of various options, but they all fail at the same root: that unless you declare your class in a special way where where these things all use all the state components (which is how records do it), the user will surely have some opinion about which field values feed into the derivation (and possibly how -- e.g., are arrays handled by identity or by content?)? And not all deriviations will want to use the same set of field values.? (And OMG what about mutability.? And for accessors, what about name selection?? Etc etc.)? When you sketch it out, you end up with something that is basically a syntax generator with about the same (enormous) programming model surface as typical "bean" generators -- which is to say, a mess, and a mess for which no solution will be complete enough.? (Our mantra for records was that zero was the only acceptable number of "knobs", because once there is one knob, there are arbitrarily many.) So while it may sound like a "logical next step", the complexity goes up by orders of magnitude, and you lose the best thing about records at the same time -- that record-ness is a semantic, not syntactic, construct.? So I am skeptical about that step. > The second feature: pattern matching on LHS of assignment. > > Suppose we have this record type: > > record Color(byte red, byte green, byte blue) {} > > and a static factory method ?someFactory? which returns a Color. > > Are there any plans to allow us to pattern match at the point of assignment like so: > > Color(byte red, byte green, byte blue) color = someFactory(); > > This would be a great addition to pattern matching. Imperative pattern matching is reasonable and well understood, but (a) it is not yet the highest-leverage remaining pattern matching feature (and so remains lower on the queue) and (b) still has several rough edges to work out.? There are actually two versions of imperative pattern matching that people might want: one which is "total" (it is a compile error to try to deconstruct a target with a pattern that is not exhaustive, and one which is "partial" (one that just throws on non-match, as if you had "cast" the target to the pattern.)?? So this is on the back burner for now. -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu Dec 5 15:21:29 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 5 Dec 2024 10:21:29 -0500 Subject: =?UTF-8?Q?Re=3A_=E2=80=9CDeriving=E2=80=9D_functionality_for_classe?= =?UTF-8?Q?s_and_pattern_matching_on_LHS_of_assignment=3F?= In-Reply-To: References: Message-ID: <544e0f5d-101f-465c-9100-cea517f4150b@oracle.com> As a correction: annotation processors cannot do this _in place_.? This is by design: it was an anti-goal of annotation processors to turn them into macro generators. An annotation processor can (with some extra work) generate _other_ compilation units, which could even be subclasses or superclasses of the annotated class, but cannot generate members _into_ any existing class.? (Again, by design: the prime directive of annotations is that it _cannot affect the language semantics of the class being annotated_; annotations are metadata.) (I suspect people will be tempted to argue with the above, because many many people wish the world were different.? But, this argument has been had to death, and amber-dev is certainly not the place to re-hash this.) But you are correct that building one specific ad-hoc, syntax-focused annotation processor into the language would be a major mistake, because it would be mixing abstractions. On 12/5/2024 10:01 AM, Ethan McCue wrote: > (nonauthoritative opinion) > > For the first point: While it has its downsides, that capability > already exists in the form of code generating annotation processors. > > I.E. it is possible to have > > @Ordered > public record Hill(int heightAboveSeaLevel) > ? ? ? ? implements HillComparable { > } > > Generate > > interface HillComparable extends Comparable { > ? ? @Override > ? ? default int compareTo(@NotNull Hill o) { > ? ? ? ? return Comparator > .comparingInt(Hill::heightAboveSeaLevel) > ? ? ? ? ? ? ? ? .compare(this, o); > ? ? } > } > > The problem is that all such code generators - if they were built into > the language - would have restrictions on the contexts in which they > are applicable. Fundamentally records can only have toString, equals, > and hashCode derived for them because by virtue of being a record the > language knows that it is just a thin data carrier. It is much? more > dubious to?do something similar for regular?classes. > > On Thu, Dec 5, 2024 at 9:02?PM Gavin Bierman > wrote: > > I can speak to the second point: Yes, this is very much on our > radar. There has been discussion of this on this list I believe > (or maybe on the spec-experts list), and it is mentioned in early > design documents that you can read on the Amber project page [1]. > > There are other places that we would like to consider to support > patterns, e.g. in the head of lambda expressions and in enhanced > for statements. We may well do these all in one go. > > Thanks for your interest! > Gavin > > [1]: > https://openjdk.org/projects/amber/design-notes/patterns/pattern-match-semantics > https://openjdk.org/projects/amber/ > > >> On 5 Dec 2024, at 09:34, vab2048 wrote: >> >> Hi Amber team, >> >> I was wondering about the future of two different features and >> thought I would just ask the mailing list. >> >> The first feature: deriving instances. >> >> Haskell allows type declarations to derive instances for certain >> type classes (Eq, Ord, Enum, Bounded, Show, and Read). >> >> Is it possible to get some sort of equivalent for java classes >> which would allow us to specify to the compiler to auto derive >> some code. I am thinking about easily auto-generating a toString, >> equals, hash code etc? We already have a form of this for >> records, and so bringing it to classes would make a logical next >> step. >> >> The second feature: pattern matching on LHS of assignment. >> >> Suppose we have this record type: >> >> record Color(byte red, byte green, byte blue) {} >> >> and a static factory method ?someFactory? which returns a Color. >> >> Are there any plans to allow us to pattern match at the point of >> assignment like so: >> >> Color(byte red, byte green, byte blue) color = someFactory(); >> >> This would be a great addition to pattern matching. >> >> >> Regards, >> >> Vikram >> >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From zjx001202 at gmail.com Thu Dec 5 16:32:41 2024 From: zjx001202 at gmail.com (Glavo) Date: Fri, 6 Dec 2024 00:32:41 +0800 Subject: =?UTF-8?Q?Re=3A_=E2=80=9CDeriving=E2=80=9D_functionality_for_classes_and_pat?= =?UTF-8?Q?tern_matching_on_LHS_of_assignment=3F?= In-Reply-To: <4d03fa54-f8c7-4315-8c07-8d21009c6ddd@oracle.com> References: <4d03fa54-f8c7-4315-8c07-8d21009c6ddd@oracle.com> Message-ID: Is it possible to solve this issue by making Java support invokeDynamic syntactically? Users can provide their own helper classes similar to java.lang.runtime.ObjectMethods to synthesize methods. Glavo On Thu, Dec 5, 2024 at 11:16?PM Brian Goetz wrote: > > > > On 12/5/2024 4:34 AM, vab2048 wrote: > > Hi Amber team, > > I was wondering about the future of two different features and thought I would just ask the mailing list. > > The first feature: deriving instances. > > Haskell allows type declarations to derive instances for certain type classes (Eq, Ord, Enum, Bounded, Show, and Read). > > Is it possible to get some sort of equivalent for java classes which would allow us to specify to the compiler to auto derive some code. I am thinking about easily auto-generating a toString, equals, hash code etc? We already have a form of this for records, and so bringing it to classes would make a logical next step. > > > The strict equivalent of this is records: in Haskell, you don't get any > control over how to derive type classes such as Eq and Show, and similarly > for records: the one the compiler gives uses all the state. So in some > sense, mission accomplished. But that's not really what you're asking. > What you're asking is for an _arbitrary class_ -- not just a `data` type -- > to be able to get these somehow. > > We did several extensive explorations of various options, but they all > fail at the same root: that unless you declare your class in a special way > where where these things all use all the state components (which is how > records do it), the user will surely have some opinion about which field > values feed into the derivation (and possibly how -- e.g., are arrays > handled by identity or by content?) And not all deriviations will want to > use the same set of field values. (And OMG what about mutability. And for > accessors, what about name selection? Etc etc.) When you sketch it out, > you end up with something that is basically a syntax generator with about > the same (enormous) programming model surface as typical "bean" generators > -- which is to say, a mess, and a mess for which no solution will be > complete enough. (Our mantra for records was that zero was the only > acceptable number of "knobs", because once there is one knob, there are > arbitrarily many.) > > So while it may sound like a "logical next step", the complexity goes up > by orders of magnitude, and you lose the best thing about records at the > same time -- that record-ness is a semantic, not syntactic, construct. So > I am skeptical about that step. > > The second feature: pattern matching on LHS of assignment. > > Suppose we have this record type: > > record Color(byte red, byte green, byte blue) {} > > and a static factory method ?someFactory? which returns a Color. > > Are there any plans to allow us to pattern match at the point of assignment like so: > > Color(byte red, byte green, byte blue) color = someFactory(); > > This would be a great addition to pattern matching. > > > Imperative pattern matching is reasonable and well understood, but (a) it > is not yet the highest-leverage remaining pattern matching feature (and so > remains lower on the queue) and (b) still has several rough edges to work > out. There are actually two versions of imperative pattern matching that > people might want: one which is "total" (it is a compile error to try to > deconstruct a target with a pattern that is not exhaustive, and one which > is "partial" (one that just throws on non-match, as if you had "cast" the > target to the pattern.) So this is on the back burner for now. > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu Dec 5 16:39:21 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 5 Dec 2024 11:39:21 -0500 Subject: =?UTF-8?Q?Re=3A_=E2=80=9CDeriving=E2=80=9D_functionality_for_classe?= =?UTF-8?Q?s_and_pattern_matching_on_LHS_of_assignment=3F?= In-Reply-To: References: <4d03fa54-f8c7-4315-8c07-8d21009c6ddd@oracle.com> Message-ID: There was some investigation into exposing invokedynamic (see the video "Below the Fold" from JVMLS a few years ago.)? I doubt that this entirely solves the issue but it is something we'd like to do someday. On 12/5/2024 11:32 AM, Glavo wrote: > Is it possible to solve this issue by making Java support > invokeDynamic syntactically? > Users can provide their own helper classes similar to > java.lang.runtime.ObjectMethods to synthesize methods. > > Glavo > > On Thu, Dec 5, 2024 at 11:16?PM Brian Goetz > wrote: > > > > > On 12/5/2024 4:34 AM, vab2048 wrote: >> Hi Amber team, >> >> I was wondering about the future of two different features and thought I would just ask the mailing list. >> >> The first feature: deriving instances. >> >> Haskell allows type declarations to derive instances for certain type classes (Eq, Ord, Enum, Bounded, Show, and Read). >> >> Is it possible to get some sort of equivalent for java classes which would allow us to specify to the compiler to auto derive some code. I am thinking about easily auto-generating a toString, equals, hash code etc? We already have a form of this for records, and so bringing it to classes would make a logical next step. > > The strict equivalent of this is records: in Haskell, you don't > get any control over how to derive type classes such as Eq and > Show, and similarly for records: the one the compiler gives uses > all the state.? So in some sense, mission accomplished.? But > that's not really what you're asking.? What you're asking is for > an _arbitrary class_ -- not just a `data` type -- to be able to > get these somehow. > > We did several extensive explorations of various options, but they > all fail at the same root: that unless you declare your class in a > special way where where these things all use all the state > components (which is how records do it), the user will surely have > some opinion about which field values feed into the derivation > (and possibly how -- e.g., are arrays handled by identity or by > content?)? And not all deriviations will want to use the same set > of field values. (And OMG what about mutability.? And for > accessors, what about name selection?? Etc etc.)? When you sketch > it out, you end up with something that is basically a syntax > generator with about the same (enormous) programming model surface > as typical "bean" generators -- which is to say, a mess, and a > mess for which no solution will be complete enough.? (Our mantra > for records was that zero was the only acceptable number of > "knobs", because once there is one knob, there are arbitrarily many.) > > So while it may sound like a "logical next step", the complexity > goes up by orders of magnitude, and you lose the best thing about > records at the same time -- that record-ness is a semantic, not > syntactic, construct.? So I am skeptical about that step. > >> The second feature: pattern matching on LHS of assignment. >> >> Suppose we have this record type: >> >> record Color(byte red, byte green, byte blue) {} >> >> and a static factory method ?someFactory? which returns a Color. >> >> Are there any plans to allow us to pattern match at the point of assignment like so: >> >> Color(byte red, byte green, byte blue) color = someFactory(); >> >> This would be a great addition to pattern matching. > > Imperative pattern matching is reasonable and well understood, but > (a) it is not yet the highest-leverage remaining pattern matching > feature (and so remains lower on the queue) and (b) still has > several rough edges to work out.? There are actually two versions > of imperative pattern matching that people might want: one which > is "total" (it is a compile error to try to deconstruct a target > with a pattern that is not exhaustive, and one which is "partial" > (one that just throws on non-match, as if you had "cast" the > target to the pattern.)?? So this is on the back burner for now. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fw at deneb.enyo.de Sat Dec 7 13:36:38 2024 From: fw at deneb.enyo.de (Florian Weimer) Date: Sat, 07 Dec 2024 14:36:38 +0100 Subject: Constructing records through reflection and module restrictions Message-ID: <87v7vv4ntl.fsf@mid.deneb.enyo.de> As far as I can see, constructing through reflection currently needs access to the record constructor. Try to use MethodHandles.lookup() to access the constructor from a different module, I get: java.lang.IllegalAccessException: symbolic reference class is not accessible: C1, from class C2 (module M) If I use the Class instance for the record with MethodHandles.privateLookupIn(), creating the lookup fails with: java.lang.IllegalAccessException: module M1 does not read module M2 If I understand this correctly, in general, this is required to preserve module encapsulation. For record classes, I assume a different choice could be made. Has there been any discussion whether it is important to restrict the creation of forged record instances? The current behavior allows using records as capabilities: The constructor invocation might be restricted to certain contexts that perform additional checks before construction. Exposing the constructor would allow bypassing that. On the other hand, access to constructors would enable programming patterns were records are created through some form of deserialization, dynamically based on record layout (for example, a CSV file reader that produces a record for every input row). But perhaps I'm wrong and there is a way to create record instances using unprivileged reflection. From brian.goetz at oracle.com Sat Dec 7 13:40:13 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 7 Dec 2024 13:40:13 +0000 Subject: Constructing records through reflection and module restrictions In-Reply-To: <87v7vv4ntl.fsf@mid.deneb.enyo.de> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> Message-ID: <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> Let?s take about 100 steps back. Why do you think that records should be immune to the ordinary access control of the language? And why are you focusing only on the constructor and not the other members of the record that presumably would be needed to access its state? Why is modularity special here and not private records? There are a whole host of assumptions in this line of thinking, and I think we should start at the beginning. What problem are you trying to solve? Sent from my iPad > On Dec 7, 2024, at 8:36?AM, Florian Weimer wrote: > > ?As far as I can see, constructing through reflection currently needs > access to the record constructor. Try to use MethodHandles.lookup() > to access the constructor from a different module, I get: > > java.lang.IllegalAccessException: symbolic reference class is not accessible: C1, from class C2 (module M) > > If I use the Class instance for the record with > MethodHandles.privateLookupIn(), creating the lookup fails with: > > java.lang.IllegalAccessException: module M1 does not read module M2 > > If I understand this correctly, in general, this is required to > preserve module encapsulation. For record classes, I assume a > different choice could be made. Has there been any discussion whether > it is important to restrict the creation of forged record instances? > The current behavior allows using records as capabilities: The > constructor invocation might be restricted to certain contexts that > perform additional checks before construction. Exposing the > constructor would allow bypassing that. On the other hand, access to > constructors would enable programming patterns were records are > created through some form of deserialization, dynamically based on > record layout (for example, a CSV file reader that produces a record > for every input row). > > But perhaps I'm wrong and there is a way to create record instances > using unprivileged reflection. From fw at deneb.enyo.de Sat Dec 7 20:35:56 2024 From: fw at deneb.enyo.de (Florian Weimer) Date: Sat, 07 Dec 2024 21:35:56 +0100 Subject: Constructing records through reflection and module restrictions In-Reply-To: <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> (Brian Goetz's message of "Sat, 7 Dec 2024 13:40:13 +0000") References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> Message-ID: <87o71ngrir.fsf@mid.deneb.enyo.de> * Brian Goetz: > Let?s take about 100 steps back. Why do you think that records > should be immune to the ordinary access control of the language? I think of them of named tuples. Tuples don't have this type of access control. But of course, one could argue that once names are involved, the matter of access control arises. I had not considered this. > And why are you focusing only on the constructor and not the other > members of the record that presumably would be needed to access its > state? Why is modularity special here and not private records? It's true that similar considerations applies to component access. This can sometimes be worked around by implementing a suitable interface. > There are a whole host of assumptions in this line of thinking, and > I think we should start at the beginning. What problem are you > trying to solve? Syntax-wise, it is very tempting to use this with very localized record types for various kinds of custom deserialization scenarios. For example, to read a CSV file with two colums, something like this could be used: record Row(String name, int index) {} var csv = CSVReader.newReader(r, Row.class); while (true) { var row = csv.readRow(); if (row == null) break; // Use the row variable. ... } But it would equally work for SQL result set rows, binary structures, and so on. I think some people use interfaces and java.lang.reflect.Proxy for a similar purpose, hoping that method declaration order matches reflection order (not a good idea, I know). As far as I can see, the proxy mechanism does not perform a module encapsulation check and can create instaces at points where a regular class declaration with an implements clause could not reference to the interface. Records would be a better replacement because they provide ordering of components. From brian.goetz at oracle.com Sat Dec 7 21:11:55 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 7 Dec 2024 16:11:55 -0500 Subject: Constructing records through reflection and module restrictions In-Reply-To: <87o71ngrir.fsf@mid.deneb.enyo.de> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> Message-ID: <628e33c3-7591-4d48-b2d3-b170d1c61c64@oracle.com> On 12/7/2024 3:35 PM, Florian Weimer wrote: > * Brian Goetz: > >> Let?s take about 100 steps back. Why do you think that records >> should be immune to the ordinary access control of the language? > I think of them of named tuples. Tuples don't have this type of > access control. But of course, one could argue that once names are > involved, the matter of access control arises. I had not considered > this. And further, records are _classes_.? They have some extra specification (which comes from java.lang.Record), and some special syntax, but like enums, they boil down to ordinary classes. Further^2, it should be possible to compatibly migrate between classes and records (as you can with enums) if you reach the limits of what records (enums) can do.? So it would be very weird to have them be magically transparent. > For example, to read a CSV file with two colums, something like this > could be used: > > record Row(String name, int index) {} Sure, but what is stopping you from making Row public/exported, if that's the case?? There's nothing private or secret about it. From forax at univ-mlv.fr Sat Dec 7 22:34:08 2024 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 7 Dec 2024 23:34:08 +0100 (CET) Subject: Constructing records through reflection and module restrictions In-Reply-To: <87o71ngrir.fsf@mid.deneb.enyo.de> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> Message-ID: <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> ----- Original Message ----- > From: "Florian Weimer" > To: "Brian Goetz" > Cc: "amber-dev" > Sent: Saturday, December 7, 2024 9:35:56 PM > Subject: Re: Constructing records through reflection and module restrictions > * Brian Goetz: > >> Let?s take about 100 steps back. Why do you think that records >> should be immune to the ordinary access control of the language? > > I think of them of named tuples. Tuples don't have this type of > access control. But of course, one could argue that once names are > involved, the matter of access control arises. I had not considered > this. > >> And why are you focusing only on the constructor and not the other >> members of the record that presumably would be needed to access its >> state? Why is modularity special here and not private records? > > It's true that similar considerations applies to component access. > This can sometimes be worked around by implementing a suitable > interface. > >> There are a whole host of assumptions in this line of thinking, and >> I think we should start at the beginning. What problem are you >> trying to solve? > > Syntax-wise, it is very tempting to use this with very localized > record types for various kinds of custom deserialization scenarios. > For example, to read a CSV file with two colums, something like this > could be used: > > record Row(String name, int index) {} > var csv = CSVReader.newReader(r, Row.class); > while (true) { > var row = csv.readRow(); > if (row == null) > break; > // Use the row variable. > ... > } > > But it would equally work for SQL result set rows, binary structures, > and so on. Why not sending the lookup object here : var csv = CSVReader.newReader(r, Row.class, MethodHandles.lookup()); > > I think some people use interfaces and java.lang.reflect.Proxy for a > similar purpose, hoping that method declaration order matches > reflection order (not a good idea, I know). As far as I can see, the > proxy mechanism does not perform a module encapsulation check and can > create instaces at points where a regular class declaration with an > implements clause could not reference to the interface. Records would > be a better replacement because they provide ordering of components. If you use an abstract deconstructors/pattern method, you get the declaration order interface Row { abstract deconstructor (String name, int index) Row(); // or a similar syntax } ... Row(var name, var index) = csv.readRow(); // use name and index here and i suppose that j.l.r.Proxy will be updated to implement such pattern. regards, R?mi From fw at deneb.enyo.de Sun Dec 8 15:15:43 2024 From: fw at deneb.enyo.de (Florian Weimer) Date: Sun, 08 Dec 2024 16:15:43 +0100 Subject: Constructing records through reflection and module restrictions In-Reply-To: <628e33c3-7591-4d48-b2d3-b170d1c61c64@oracle.com> (Brian Goetz's message of "Sat, 7 Dec 2024 16:11:55 -0500") References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <628e33c3-7591-4d48-b2d3-b170d1c61c64@oracle.com> Message-ID: <87v7vufbog.fsf@mid.deneb.enyo.de> * Brian Goetz: > On 12/7/2024 3:35 PM, Florian Weimer wrote: >> * Brian Goetz: >> >>> Let?s take about 100 steps back. Why do you think that records >>> should be immune to the ordinary access control of the language? >> I think of them of named tuples. Tuples don't have this type of >> access control. But of course, one could argue that once names are >> involved, the matter of access control arises. I had not considered >> this. > > And further, records are _classes_.? They have some extra specification > (which comes from java.lang.Record), and some special syntax, but like > enums, they boil down to ordinary classes. Further^2, it should be > possible to compatibly migrate between classes and records (as you can > with enums) if you reach the limits of what records (enums) can do.? So > it would be very weird to have them be magically transparent. On the other hand, enums do have a bypass for certain member accesses. And this isn't something you can emulate after turning an enum into a less-constrained class. >> For example, to read a CSV file with two colums, something like this >> could be used: >> >> record Row(String name, int index) {} > > Sure, but what is stopping you from making Row public/exported, if > that's the case?? There's nothing private or secret about it. It's the syntactic overhead. The attractiveness of this pattern is that's it's a clear and concise notation for this type of deserialization. Creating a public type for it in a suitable package sort of breaks that. From brian.goetz at oracle.com Sun Dec 8 15:50:43 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 8 Dec 2024 10:50:43 -0500 Subject: Constructing records through reflection and module restrictions In-Reply-To: <87v7vufbog.fsf@mid.deneb.enyo.de> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <628e33c3-7591-4d48-b2d3-b170d1c61c64@oracle.com> <87v7vufbog.fsf@mid.deneb.enyo.de> Message-ID: <0a949c7d-a800-4e7f-844e-36694565027c@oracle.com> Sure, there are other ways we could have designed the language.? Tuples are structural types, which means they are not declared, but instead spring when the type constructor is applied to other (necessarily accessible) types. This means there is no need for access control, since anyone who can access T and U can "summon" the type `tuple`.? (We have this for arrays already -- which is already a significant source of irregularity in the language, so we chose not to emulate that.) But, we chose to lean into Java's class-based, nominal type system.? Making special exceptions "because it's like a tuple" is surely convenience in some cases, but makes the language more complicated to reason about overall. On 12/8/2024 10:15 AM, Florian Weimer wrote: > It's the syntactic overhead. The attractiveness of this pattern is > that's it's a clear and concise notation for this type of > deserialization. Creating a public type for it in a suitable package > sort of breaks that. -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Sun Dec 8 16:36:10 2024 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 8 Dec 2024 17:36:10 +0100 (CET) Subject: Constructing records through reflection and module restrictions In-Reply-To: <0a949c7d-a800-4e7f-844e-36694565027c@oracle.com> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <628e33c3-7591-4d48-b2d3-b170d1c61c64@oracle.com> <87v7vufbog.fsf@mid.deneb.enyo.de> <0a949c7d-a800-4e7f-844e-36694565027c@oracle.com> Message-ID: <1689465778.17175986.1733675770477.JavaMail.zimbra@univ-eiffel.fr> > From: "Brian Goetz" > To: "Florian Weimer" > Cc: "amber-dev" > Sent: Sunday, December 8, 2024 4:50:43 PM > Subject: Re: Constructing records through reflection and module restrictions > Sure, there are other ways we could have designed the language. Tuples are > structural types, which means they are not declared, but instead spring when > the type constructor is applied to other (necessarily accessible) types. This > means there is no need for access control, since anyone who can access T and U > can "summon" the type `tuple`. (We have this for arrays already -- which > is already a significant source of irregularity in the language, so we chose > not to emulate that.) > But, we chose to lean into Java's class-based, nominal type system. Making > special exceptions "because it's like a tuple" is surely convenience in some > cases, but makes the language more complicated to reason about overall. We have made an exception for lambdas. There is something special with tuples, most of my students now learn programming with Python as first langage, so there are used to use tuples as an element of design. As an example, when students start Java, we have a course to explain that Java has no tuples and the difference between a record and a tuple. Another example, currently, this is the time of the year where we are doing the advent of code, students can choose the langage they want, most of the undergraduate students choose Python. When asked why, having tuples is the most cited feature, and it makes sense given the kind of problems of the advent of code. I think we will have to fix this in Java at some point, not now, perhaps even not us, but exactly like we did not need lambdas because we had inner classes, not having tuples will be seen increasingly as a Java problem. regards, R?mi NB: For graduate students, most of them are using Java for the advent of code, but i suppose this is a kind of Stockholm syndrome reaction because they are using Java in most of their courses (concurrency, android, http server, design pattern, spring, etc). > On 12/8/2024 10:15 AM, Florian Weimer wrote: >> It's the syntactic overhead. The attractiveness of this pattern is >> that's it's a clear and concise notation for this type of >> deserialization. Creating a public type for it in a suitable package >> sort of breaks that. -------------- next part -------------- An HTML attachment was scrubbed... URL: From fw at deneb.enyo.de Sun Dec 8 16:52:42 2024 From: fw at deneb.enyo.de (Florian Weimer) Date: Sun, 08 Dec 2024 17:52:42 +0100 Subject: Constructing records through reflection and module restrictions In-Reply-To: <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> (Remi Forax's message of "Sat, 7 Dec 2024 23:34:08 +0100 (CET)") References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> Message-ID: <87r06if76t.fsf@mid.deneb.enyo.de> * Remi Forax: >> Syntax-wise, it is very tempting to use this with very localized >> record types for various kinds of custom deserialization scenarios. >> For example, to read a CSV file with two colums, something like this >> could be used: >> >> record Row(String name, int index) {} >> var csv = CSVReader.newReader(r, Row.class); >> while (true) { >> var row = csv.readRow(); >> if (row == null) >> break; >> // Use the row variable. >> ... >> } >> >> But it would equally work for SQL result set rows, binary structures, >> and so on. > > Why not sending the lookup object here : > > var csv = CSVReader.newReader(r, Row.class, MethodHandles.lookup()); Thanks. Not surpringly, this works for constructor access. It should help with using defineHiddenClass() as well if I read the documentation correctly (although maybe I can get what I want just using method handles). Syntax-wise, I think it's okay, although it will certainly look like magic to newcomers if this programming pattern ever catches on (and similarly in other APIs that use reflective access behind the covers). But from a conceptual perspective, it's really clear. It appears that MethodHandles.lookup() uses an intrisified getCallerClass(), so it's probably not necessary to turn this into MethodHandles::lookup, to the lookup when it is not needed. >> I think some people use interfaces and java.lang.reflect.Proxy for a >> similar purpose, hoping that method declaration order matches >> reflection order (not a good idea, I know). As far as I can see, the >> proxy mechanism does not perform a module encapsulation check and can >> create instaces at points where a regular class declaration with an >> implements clause could not reference to the interface. Records would >> be a better replacement because they provide ordering of components. > > If you use an abstract deconstructors/pattern method, you get the declaration order > > interface Row { > abstract deconstructor (String name, int index) Row(); // or a similar syntax > } > > ... > Row(var name, var index) = csv.readRow(); > // use name and index here > > and i suppose that j.l.r.Proxy will be updated to implement such pattern. Is this already under discussion somewhere? I've seen some references to generalizing pattern matching to custom types, but nothing along what you describe. From petereastham at gmail.com Mon Dec 9 01:52:32 2024 From: petereastham at gmail.com (Peter Eastham) Date: Sun, 8 Dec 2024 18:52:32 -0700 Subject: Improving Method Reference Ergonomics Message-ID: Hi Amber team, Earlier this week I was playing around with fluent API design, and I believe Java could benefit from some improvements to the usage of Method References, I'll keep this short with the following example. Lets take the following JPA Criteria from section 6.3.3 of the Specification, (Only for an example of what an API could begin doing, not should do) CriteriaQuery q = cb.createQuery(Customer.class); Root customer = q.from(Customer.class); Join order = customer.join(Customer_.orders, JoinType.LEFT); q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); If there was greater access to the Method Reference more implicit information could be passed, reducing the noise, CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) .leftJoin(Customer::orders) .where(Object::equals, Customer::status, 1); var result = q.select(); Regarding what should be available, the resolved Class and Method name at least, anything else I'd leave up to the feasibility of the change. Thanks, -Peter -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Mon Dec 9 02:30:51 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Sun, 8 Dec 2024 20:30:51 -0600 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: Hi Peter, Slightly off topic: You might be interested in the querystream library, which provides a Stream-like wrapper around JPA's Criteria API. https://github.com/querystream/querystream/ Disclaimer: I'm the author. -Archie On Sun, Dec 8, 2024 at 7:53?PM Peter Eastham wrote: > Hi Amber team, > > Earlier this week I was playing around with fluent API design, and I > believe Java could benefit from some improvements to the usage of Method > References, I'll keep this short with the following example. > > Lets take the following JPA Criteria from section 6.3.3 of the > Specification, (Only for an example of what an API could begin doing, not > should do) > CriteriaQuery q = cb.createQuery(Customer.class); > Root customer = q.from(Customer.class); > Join order = customer.join(Customer_.orders, JoinType.LEFT); > q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); > > If there was greater access to the Method Reference more implicit > information could be passed, reducing the noise, > CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) > .leftJoin(Customer::orders) > .where(Object::equals, Customer::status, 1); > var result = q.select(); > > Regarding what should be available, the resolved Class and Method name at > least, anything else I'd leave up to the feasibility of the change. > > Thanks, > -Peter > -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From petereastham at gmail.com Mon Dec 9 02:40:32 2024 From: petereastham at gmail.com (Peter Eastham) Date: Sun, 8 Dec 2024 19:40:32 -0700 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: Hey Archie, Sorry if this was off topic for Amber, is there a better email list for this type of language improvement? The JPA reference was only for a more common reference point. Not necessarily that I want that functionality in JPA itself. Thanks, -Peter On Sun, Dec 8, 2024 at 7:31?PM Archie Cobbs wrote: > Hi Peter, > > Slightly off topic: You might be interested in the querystream library, > which provides a Stream-like wrapper around JPA's Criteria API. > > https://github.com/querystream/querystream/ > > Disclaimer: I'm the author. > > -Archie > > On Sun, Dec 8, 2024 at 7:53?PM Peter Eastham > wrote: > >> Hi Amber team, >> >> Earlier this week I was playing around with fluent API design, and I >> believe Java could benefit from some improvements to the usage of Method >> References, I'll keep this short with the following example. >> >> Lets take the following JPA Criteria from section 6.3.3 of the >> Specification, (Only for an example of what an API could begin doing, not >> should do) >> CriteriaQuery q = cb.createQuery(Customer.class); >> Root customer = q.from(Customer.class); >> Join order = customer.join(Customer_.orders, JoinType.LEFT); >> q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); >> >> If there was greater access to the Method Reference more implicit >> information could be passed, reducing the noise, >> CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) >> .leftJoin(Customer::orders) >> .where(Object::equals, Customer::status, 1); >> var result = q.select(); >> >> Regarding what should be available, the resolved Class and Method name at >> least, anything else I'd leave up to the feasibility of the change. >> >> Thanks, >> -Peter >> > > > -- > Archie L. Cobbs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Mon Dec 9 02:44:48 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Sun, 8 Dec 2024 20:44:48 -0600 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: Hi Peter, My apologies! I meant that *my* email was off-topic not yours :) -Archie On Sun, Dec 8, 2024 at 8:40?PM Peter Eastham wrote: > Hey Archie, > > Sorry if this was off topic for Amber, is there a better email list for > this type of language improvement? > > The JPA reference was only for a more common reference point. Not > necessarily that I want that functionality in JPA itself. > > Thanks, > -Peter > > > On Sun, Dec 8, 2024 at 7:31?PM Archie Cobbs > wrote: > >> Hi Peter, >> >> Slightly off topic: You might be interested in the querystream library, >> which provides a Stream-like wrapper around JPA's Criteria API. >> >> https://github.com/querystream/querystream/ >> >> Disclaimer: I'm the author. >> >> -Archie >> >> On Sun, Dec 8, 2024 at 7:53?PM Peter Eastham >> wrote: >> >>> Hi Amber team, >>> >>> Earlier this week I was playing around with fluent API design, and I >>> believe Java could benefit from some improvements to the usage of Method >>> References, I'll keep this short with the following example. >>> >>> Lets take the following JPA Criteria from section 6.3.3 of the >>> Specification, (Only for an example of what an API could begin doing, not >>> should do) >>> CriteriaQuery q = cb.createQuery(Customer.class); >>> Root customer = q.from(Customer.class); >>> Join order = customer.join(Customer_.orders, JoinType.LEFT); >>> q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); >>> >>> If there was greater access to the Method Reference more implicit >>> information could be passed, reducing the noise, >>> CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) >>> .leftJoin(Customer::orders) >>> .where(Object::equals, Customer::status, 1); >>> var result = q.select(); >>> >>> Regarding what should be available, the resolved Class and Method name >>> at least, anything else I'd leave up to the feasibility of the change. >>> >>> Thanks, >>> -Peter >>> >> >> >> -- >> Archie L. Cobbs >> > -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From ethan at mccue.dev Mon Dec 9 03:42:12 2024 From: ethan at mccue.dev (Ethan McCue) Date: Mon, 9 Dec 2024 12:42:12 +0900 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: No, what he said was slightly off topic, you are fine. For this specific want project Babylon and code reflection is (I think) the direction primarily being explored. That being said I think a degree of what you want is possible. I know someone who was writing their thesis on it, though it might take me a minute to find their code On Mon, Dec 9, 2024, 12:40 PM Peter Eastham wrote: > Hey Archie, > > Sorry if this was off topic for Amber, is there a better email list for > this type of language improvement? > > The JPA reference was only for a more common reference point. Not > necessarily that I want that functionality in JPA itself. > > Thanks, > -Peter > > > On Sun, Dec 8, 2024 at 7:31?PM Archie Cobbs > wrote: > >> Hi Peter, >> >> Slightly off topic: You might be interested in the querystream library, >> which provides a Stream-like wrapper around JPA's Criteria API. >> >> https://github.com/querystream/querystream/ >> >> Disclaimer: I'm the author. >> >> -Archie >> >> On Sun, Dec 8, 2024 at 7:53?PM Peter Eastham >> wrote: >> >>> Hi Amber team, >>> >>> Earlier this week I was playing around with fluent API design, and I >>> believe Java could benefit from some improvements to the usage of Method >>> References, I'll keep this short with the following example. >>> >>> Lets take the following JPA Criteria from section 6.3.3 of the >>> Specification, (Only for an example of what an API could begin doing, not >>> should do) >>> CriteriaQuery q = cb.createQuery(Customer.class); >>> Root customer = q.from(Customer.class); >>> Join order = customer.join(Customer_.orders, JoinType.LEFT); >>> q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); >>> >>> If there was greater access to the Method Reference more implicit >>> information could be passed, reducing the noise, >>> CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) >>> .leftJoin(Customer::orders) >>> .where(Object::equals, Customer::status, 1); >>> var result = q.select(); >>> >>> Regarding what should be available, the resolved Class and Method name >>> at least, anything else I'd leave up to the feasibility of the change. >>> >>> Thanks, >>> -Peter >>> >> >> >> -- >> Archie L. Cobbs >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ethan at mccue.dev Mon Dec 9 03:45:25 2024 From: ethan at mccue.dev (Ethan McCue) Date: Mon, 9 Dec 2024 12:45:25 +0900 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: https://github.com/rilindbicaj/fluentmapper With I think the extraction being done here https://github.com/rilindbicaj/fluentmapper/blob/main/fluentmapper-provider/src/main/java/dev/bici/fluentmapper/provider/expression/classextractor/RegexExpressionClassExtractor.java Someone else would probably be able to speak better to how stable/advisable this approach is atm On Mon, Dec 9, 2024, 12:42 PM Ethan McCue wrote: > No, what he said was slightly off topic, you are fine. > > For this specific want project Babylon and code reflection is (I think) > the direction primarily being explored. That being said I think a degree of > what you want is possible. I know someone who was writing their thesis on > it, though it might take me a minute to find their code > > On Mon, Dec 9, 2024, 12:40 PM Peter Eastham > wrote: > >> Hey Archie, >> >> Sorry if this was off topic for Amber, is there a better email list for >> this type of language improvement? >> >> The JPA reference was only for a more common reference point. Not >> necessarily that I want that functionality in JPA itself. >> >> Thanks, >> -Peter >> >> >> On Sun, Dec 8, 2024 at 7:31?PM Archie Cobbs >> wrote: >> >>> Hi Peter, >>> >>> Slightly off topic: You might be interested in the querystream library, >>> which provides a Stream-like wrapper around JPA's Criteria API. >>> >>> https://github.com/querystream/querystream/ >>> >>> Disclaimer: I'm the author. >>> >>> -Archie >>> >>> On Sun, Dec 8, 2024 at 7:53?PM Peter Eastham >>> wrote: >>> >>>> Hi Amber team, >>>> >>>> Earlier this week I was playing around with fluent API design, and I >>>> believe Java could benefit from some improvements to the usage of Method >>>> References, I'll keep this short with the following example. >>>> >>>> Lets take the following JPA Criteria from section 6.3.3 of the >>>> Specification, (Only for an example of what an API could begin doing, not >>>> should do) >>>> CriteriaQuery q = cb.createQuery(Customer.class); >>>> Root customer = q.from(Customer.class); >>>> Join order = customer.join(Customer_.orders, JoinType.LEFT); >>>> q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); >>>> >>>> If there was greater access to the Method Reference more implicit >>>> information could be passed, reducing the noise, >>>> CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) >>>> .leftJoin(Customer::orders) >>>> .where(Object::equals, Customer::status, 1); >>>> var result = q.select(); >>>> >>>> Regarding what should be available, the resolved Class and Method name >>>> at least, anything else I'd leave up to the feasibility of the change. >>>> >>>> Thanks, >>>> -Peter >>>> >>> >>> >>> -- >>> Archie L. Cobbs >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Mon Dec 9 15:35:23 2024 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 9 Dec 2024 16:35:23 +0100 (CET) Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: <1117279302.17749628.1733758523963.JavaMail.zimbra@univ-eiffel.fr> Hello are you aware of Jakarta data API ? [ https://github.com/jakartaee/data | https://github.com/jakartaee/data ] Which is quite similar to Spring Data and provide a typesafe API, here is a presentation by Gavin King https://www.youtube.com/watch?v=X9GplCb5SWY For me the static meta-model does exactly what you want. regards, R?mi > From: "Peter Eastham" > To: "amber-dev" > Sent: Monday, December 9, 2024 2:52:32 AM > Subject: Improving Method Reference Ergonomics > Hi Amber team, > Earlier this week I was playing around with fluent API design, and I believe > Java could benefit from some improvements to the usage of Method References, > I'll keep this short with the following example. > Lets take the following JPA Criteria from section 6.3.3 of the Specification, > (Only for an example of what an API could begin doing, not should do) > CriteriaQuery q = cb.createQuery(Customer.class); > Root customer = q.from(Customer.class); > Join order = customer.join(Customer_.orders, JoinType.LEFT); > q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); > If there was greater access to the Method Reference more implicit information > could be passed, reducing the noise, > CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) > .leftJoin(Customer::orders) > .where(Object::equals, Customer::status, 1); > var result = q.select(); > Regarding what should be available, the resolved Class and Method name at least, > anything else I'd leave up to the feasibility of the change. > Thanks, > -Peter -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Dec 9 15:39:02 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 9 Dec 2024 10:39:02 -0500 Subject: Constructing records through reflection and module restrictions In-Reply-To: <87r06if76t.fsf@mid.deneb.enyo.de> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> <87r06if76t.fsf@mid.deneb.enyo.de> Message-ID: There is a better approach than passing around the Lookup (which requires everyone to coordinate around the Lookup capability): use open modules.? THe concept of "open module" was designed for exactly this purpose: to allow packages to be "exported for reflection" so that frameworks can reflect over them more liberally than bytecode linkage would permit.? If you put your domain objects in a package that is opened (either to the framework, or to everyone), no need to play games with Lookup. On 12/8/2024 11:52 AM, Florian Weimer wrote: > * Remi Forax: > >>> Syntax-wise, it is very tempting to use this with very localized >>> record types for various kinds of custom deserialization scenarios. >>> For example, to read a CSV file with two colums, something like this >>> could be used: >>> >>> record Row(String name, int index) {} >>> var csv = CSVReader.newReader(r, Row.class); >>> while (true) { >>> var row = csv.readRow(); >>> if (row == null) >>> break; >>> // Use the row variable. >>> ... >>> } >>> >>> But it would equally work for SQL result set rows, binary structures, >>> and so on. >> Why not sending the lookup object here : >> >> var csv = CSVReader.newReader(r, Row.class, MethodHandles.lookup()); > Thanks. Not surpringly, this works for constructor access. It should > help with using defineHiddenClass() as well if I read the > documentation correctly (although maybe I can get what I want just > using method handles). Syntax-wise, I think it's okay, although it > will certainly look like magic to newcomers if this programming > pattern ever catches on (and similarly in other APIs that use > reflective access behind the covers). But from a conceptual > perspective, it's really clear. > > It appears that MethodHandles.lookup() uses an intrisified > getCallerClass(), so it's probably not necessary to turn this into > MethodHandles::lookup, to the lookup when it is not needed. > >>> I think some people use interfaces and java.lang.reflect.Proxy for a >>> similar purpose, hoping that method declaration order matches >>> reflection order (not a good idea, I know). As far as I can see, the >>> proxy mechanism does not perform a module encapsulation check and can >>> create instaces at points where a regular class declaration with an >>> implements clause could not reference to the interface. Records would >>> be a better replacement because they provide ordering of components. >> If you use an abstract deconstructors/pattern method, you get the declaration order >> >> interface Row { >> abstract deconstructor (String name, int index) Row(); // or a similar syntax >> } >> >> ... >> Row(var name, var index) = csv.readRow(); >> // use name and index here >> >> and i suppose that j.l.r.Proxy will be updated to implement such pattern. > Is this already under discussion somewhere? I've seen some references > to generalizing pattern matching to custom types, but nothing along > what you describe. -------------- next part -------------- An HTML attachment was scrubbed... URL: From petereastham at gmail.com Mon Dec 9 15:46:04 2024 From: petereastham at gmail.com (Peter Eastham) Date: Mon, 9 Dec 2024 08:46:04 -0700 Subject: Improving Method Reference Ergonomics In-Reply-To: <1117279302.17749628.1733758523963.JavaMail.zimbra@univ-eiffel.fr> References: <1117279302.17749628.1733758523963.JavaMail.zimbra@univ-eiffel.fr> Message-ID: Hey Remi, My usage of JPA was more for a common point of reference, as I figured most Java Developers who would subscribe to Amber would have interacted with it at one point or another. Not necessarily my personal use case, nor current need. I did another review of the Static Meta-Model this morning. I agree it accomplishes the same scope as what I would like with the Method Reference Improvements, however it isn't an option the moment we stop dealing within JPA. I'll review Ethan's links and write a more full overview which I'll post to the Babylon Project's list before the end of the year. (Assuming I don't get too distracted with the Class File Api) Thanks everyone, -Peter On Mon, Dec 9, 2024 at 8:35?AM Remi Forax wrote: > Hello > are you aware of Jakarta data API ? > https://github.com/jakartaee/data > > Which is quite similar to Spring Data and provide a typesafe API, > here is a presentation by Gavin King > https://www.youtube.com/watch?v=X9GplCb5SWY > > For me the static meta-model does exactly what you want. > > regards, > R?mi > > ------------------------------ > > *From: *"Peter Eastham" > *To: *"amber-dev" > *Sent: *Monday, December 9, 2024 2:52:32 AM > *Subject: *Improving Method Reference Ergonomics > > Hi Amber team, > > Earlier this week I was playing around with fluent API design, and I > believe Java could benefit from some improvements to the usage of Method > References, I'll keep this short with the following example. > > Lets take the following JPA Criteria from section 6.3.3 of the > Specification, (Only for an example of what an API could begin doing, not > should do) > CriteriaQuery q = cb.createQuery(Customer.class); > Root customer = q.from(Customer.class); > Join order = customer.join(Customer_.orders, JoinType.LEFT); > q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); > > If there was greater access to the Method Reference more implicit > information could be passed, reducing the noise, > CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) > .leftJoin(Customer::orders) > .where(Object::equals, Customer::status, 1); > var result = q.select(); > > Regarding what should be available, the resolved Class and Method name at > least, anything else I'd leave up to the feasibility of the change. > > Thanks, > -Peter > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pedro.lamarao at prodist.com.br Mon Dec 9 15:47:31 2024 From: pedro.lamarao at prodist.com.br (=?UTF-8?Q?Pedro_Lamar=C3=A3o?=) Date: Mon, 9 Dec 2024 12:47:31 -0300 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: Em dom., 8 de dez. de 2024 ?s 22:53, Peter Eastham escreveu: > If there was greater access to the Method Reference more implicit > information could be passed, reducing the noise, > CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) > .leftJoin(Customer::orders) > .where(Object::equals, Customer::status, 1); > var result = q.select(); > > Is this about having the expression Customer::status evaluate to, say, a VarHandle for getting / setting the status attribute? I am reminded of C# properties which seem to me a peculiar intermediate kind of thing between attributes and methods. -- Pedro Lamar?o -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Dec 9 15:56:23 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 9 Dec 2024 10:56:23 -0500 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: <325d5ac9-4fd0-40a5-b51b-d1575378a89a@oracle.com> By "greater access", I think you mean "if they could be reflected on as a function, not just a thunk of behavior", yes?? Then `createQuery(Customer::new)` would be able to reflect over the constructor reference and see "oh, it's a constructor for Customer". We've given a good deal of thought to this problem, but it's messy for a number of reasons, including erasure and limitations on the static type system.? Does createQuery mean to limit to method references, rather than all lambdas?? If so, then Supplier is not a sharp enough type, and users could pass a Supplier that ends up causing a dynamic failure.? If not, then it sounds like what you want is to reflect over the concrete shape of the supplier, which runs into erasure problems (among others -- what if you intended a Supplier, but the lambda you passed instantiates a Supplier where the subtype is inaccessible to the framework.) So while it is possible to associate more metadata with method references than we currently do, and we've considered it, most of the obvious paths run into obvious roadblocks just a bit farther down the road. On 12/8/2024 8:52 PM, Peter Eastham wrote: > Hi Amber team, > > Earlier this week I was playing around with fluent API design, and I > believe Java could benefit from some improvements to the usage of > Method References, I'll keep this short with the following example. > > Lets take the following JPA Criteria from section 6.3.3 of the > Specification, (Only for an example of what an API could begin doing, > not should do) > CriteriaQuery q = cb.createQuery(Customer.class); > Root customer = q.from(Customer.class); > Join order = customer.join(Customer_.orders, JoinType.LEFT); > q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); > > If there was greater access to the Method Reference more implicit > information could be passed, reducing the noise, > CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) > ? .leftJoin(Customer::orders) > ? .where(Object::equals, Customer::status, 1); > var result = q.select(); > > Regarding what should be available, the resolved Class and Method name > at least, anything else I'd leave up to the feasibility of the change. > > Thanks, > -Peter -------------- next part -------------- An HTML attachment was scrubbed... URL: From petereastham at gmail.com Mon Dec 9 17:30:15 2024 From: petereastham at gmail.com (Peter Eastham) Date: Mon, 9 Dec 2024 10:30:15 -0700 Subject: Improving Method Reference Ergonomics In-Reply-To: <325d5ac9-4fd0-40a5-b51b-d1575378a89a@oracle.com> References: <325d5ac9-4fd0-40a5-b51b-d1575378a89a@oracle.com> Message-ID: Hey Brian, I'm hesitant to respond further, as I'd like some time to do a proper write up that can provide a more solid context for discussion than my simple example provided. You are right in that "createQuery(Customer::new)" would be behaving around the Constructor, instead of utilizing it as a "Supplier". The exact type this would use is not something I have fully considered, and I agree that the current Functional Interfaces aren't sharp enough to restrict it to only Method References. It's also not a solution to have Method References resolve to their own type without being able to still work in those situations. When you say Dynamic Failure, can you explain that a bit more? My assumption is that there it would be an issue if you dynamically transform the class, specifically the method in the reference. However I'm unsure if that is any different of a failure than if you did the same with the current use case. Thanks, -Peter On Mon, Dec 9, 2024 at 8:56?AM Brian Goetz wrote: > By "greater access", I think you mean "if they could be reflected on as a > function, not just a thunk of behavior", yes? Then > `createQuery(Customer::new)` would be able to reflect over the constructor > reference and see "oh, it's a constructor for Customer". > > We've given a good deal of thought to this problem, but it's messy for a > number of reasons, including erasure and limitations on the static type > system. Does createQuery mean to limit to method references, rather than > all lambdas? If so, then Supplier is not a sharp enough type, and users > could pass a Supplier that ends up causing a dynamic failure. If not, then > it sounds like what you want is to reflect over the concrete shape of the > supplier, which runs into erasure problems (among others -- what if you > intended a Supplier, but the lambda you passed instantiates a > Supplier where the subtype is inaccessible to the > framework.) > > So while it is possible to associate more metadata with method references > than we currently do, and we've considered it, most of the obvious paths > run into obvious roadblocks just a bit farther down the road. > > > > > On 12/8/2024 8:52 PM, Peter Eastham wrote: > > Hi Amber team, > > Earlier this week I was playing around with fluent API design, and I > believe Java could benefit from some improvements to the usage of Method > References, I'll keep this short with the following example. > > Lets take the following JPA Criteria from section 6.3.3 of the > Specification, (Only for an example of what an API could begin doing, not > should do) > CriteriaQuery q = cb.createQuery(Customer.class); > Root customer = q.from(Customer.class); > Join order = customer.join(Customer_.orders, JoinType.LEFT); > q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); > > If there was greater access to the Method Reference more implicit > information could be passed, reducing the noise, > CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) > .leftJoin(Customer::orders) > .where(Object::equals, Customer::status, 1); > var result = q.select(); > > Regarding what should be available, the resolved Class and Method name at > least, anything else I'd leave up to the feasibility of the change. > > Thanks, > -Peter > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Dec 9 17:40:45 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 9 Dec 2024 12:40:45 -0500 Subject: Improving Method Reference Ergonomics In-Reply-To: References: <325d5ac9-4fd0-40a5-b51b-d1575378a89a@oracle.com> Message-ID: <2c40a945-732f-48e8-95e2-ffb478e8e6d1@oracle.com> The design center for lambdas and method reference is that the key concept is _functional interfaces_, which can be thought of as nominal function types. Both lambdas and method references are expressions that evaluate to instances of functional interfaces.? When you have a method m(Supplier s), you can create s with a lambda, a method or constructor references, with an anonymous subclass of Supplier, with an instance of a named subclass of Supplier, etc.? Once you have a Supplier, how it came into being is irrelevant. Saying that conversion from method references to functional interface instances carries extra metadata (e.g., some extra interface like IAmAMethodRef, from which you could get the symbolic information about what method it refers to), is a viable feature idea.? However, a method like m(Supplier s) that really wants a method ref, has no way to express this in the method signature.? This means that if I pass it `m(() -> new Foo(7))`, when `m` tries to cast its supplier to IAmAMethodRef, it would get a CCE or similar.? THis is what I mean by a dynamic failure -- you wrote a program which conforms to the static type system, but you still managed to pass "bad data" to a method. Now, maybe you want more, not only for method refs to be scrutable, but to add some new types, like ConstructorRef.? Then we could claw back static type safety, at the cost of more complexity, and potential ambiguity (What if there is an overload between m(Supplier) and m(ConstructorRef, should the language try to resolve that?) All of this is to say, this is a viable part of the design space, but the incremental expressiveness is lower than you might think, and the incremental cost and complexity is higher than you might think. On 12/9/2024 12:30 PM, Peter Eastham wrote: > Hey Brian, > > I'm hesitant to respond further, as I'd like some time to do a proper > write up that can provide a more solid context for discussion than my > simple example provided. > > You are right in that "createQuery(Customer::new)" would be behaving > around the Constructor, instead of utilizing it as a > "Supplier". The exact type this would use is not something I > have fully considered, and I agree that the current Functional > Interfaces aren't sharp enough to restrict it to only Method > References. It's also not a solution to have Method References resolve > to their own type without being able to still work in those situations. > > When you say Dynamic Failure, can you explain that a bit more? My > assumption is that there it would be an issue if you dynamically > transform the class, specifically the method in the reference. However > I'm unsure if that is any different of a failure than if you did the > same with the current use case. > > Thanks, > -Peter > > On Mon, Dec 9, 2024 at 8:56?AM Brian Goetz wrote: > > By "greater access", I think you mean "if they could be reflected > on as a function, not just a thunk of behavior", yes?? Then > `createQuery(Customer::new)` would be able to reflect over the > constructor reference and see "oh, it's a constructor for Customer". > > We've given a good deal of thought to this problem, but it's messy > for a number of reasons, including erasure and limitations on the > static type system.? Does createQuery mean to limit to method > references, rather than all lambdas?? If so, then Supplier is > not a sharp enough type, and users could pass a Supplier that ends > up causing a dynamic failure.? If not, then it sounds like what > you want is to reflect over the concrete shape of the supplier, > which runs into erasure problems (among others -- what if you > intended a Supplier, but the lambda you passed instantiates a > Supplier where the subtype is inaccessible to the > framework.) > > So while it is possible to associate more metadata with method > references than we currently do, and we've considered it, most of > the obvious paths run into obvious roadblocks just a bit farther > down the road. > > > > > On 12/8/2024 8:52 PM, Peter Eastham wrote: >> Hi Amber team, >> >> Earlier this week I was playing around with fluent API design, >> and I believe Java could benefit from some improvements to the >> usage of Method References, I'll keep this short with the >> following example. >> >> Lets take the following JPA Criteria from section 6.3.3 of the >> Specification, (Only for an example of what an API could begin >> doing, not should do) >> CriteriaQuery q = cb.createQuery(Customer.class); >> Root customer = q.from(Customer.class); >> Join order = customer.join(Customer_.orders, JoinType.LEFT); >> q.where(cb.equal(customer.get(Customer_.status), >> 1)).select(customer); >> >> If there was greater access to the Method Reference more implicit >> information could be passed, reducing the noise, >> CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) >> ? .leftJoin(Customer::orders) >> ? .where(Object::equals, Customer::status, 1); >> var result = q.select(); >> >> Regarding what should be available, the resolved Class and Method >> name at least, anything else I'd leave up to the feasibility of >> the change. >> >> Thanks, >> -Peter > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rotanolexandr842 at gmail.com Mon Dec 9 18:22:35 2024 From: rotanolexandr842 at gmail.com (Olexandr Rotan) Date: Mon, 9 Dec 2024 20:22:35 +0200 Subject: Constructing records through reflection and module restrictions In-Reply-To: References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> <87r06if76t.fsf@mid.deneb.enyo.de> Message-ID: Little of topic here, but what I was lacking with opening is opens * to X (similar to exports * to X). For example, I want my module to be open to code that I trust like spring framework, but not accessible to some 3rd party API wrappers. Something like this would be really helpful in situations when working with sensitive user data, because otherwise you either have to give up access control using open module or open packages one by one to each module which is virtually unmaintainable. Putting everything "open" is not really an option since like 95% of code has to be open to reflection if working with IoC containers and ORM`s On Mon, Dec 9, 2024, 19:07 Brian Goetz wrote: > There is a better approach than passing around the Lookup (which requires > everyone to coordinate around the Lookup capability): use open modules. > THe concept of "open module" was designed for exactly this purpose: to > allow packages to be "exported for reflection" so that frameworks can > reflect over them more liberally than bytecode linkage would permit. If > you put your domain objects in a package that is opened (either to the > framework, or to everyone), no need to play games with Lookup. > > > On 12/8/2024 11:52 AM, Florian Weimer wrote: > > * Remi Forax: > > > Syntax-wise, it is very tempting to use this with very localized > record types for various kinds of custom deserialization scenarios. > For example, to read a CSV file with two colums, something like this > could be used: > > record Row(String name, int index) {} > var csv = CSVReader.newReader(r, Row.class); > while (true) { > var row = csv.readRow(); > if (row == null) > break; > // Use the row variable. > ... > } > > But it would equally work for SQL result set rows, binary structures, > and so on. > > > Why not sending the lookup object here : > > var csv = CSVReader.newReader(r, Row.class, MethodHandles.lookup()); > > > Thanks. Not surpringly, this works for constructor access. It should > help with using defineHiddenClass() as well if I read the > documentation correctly (although maybe I can get what I want just > using method handles). Syntax-wise, I think it's okay, although it > will certainly look like magic to newcomers if this programming > pattern ever catches on (and similarly in other APIs that use > reflective access behind the covers). But from a conceptual > perspective, it's really clear. > > It appears that MethodHandles.lookup() uses an intrisified > getCallerClass(), so it's probably not necessary to turn this into > MethodHandles::lookup, to the lookup when it is not needed. > > > I think some people use interfaces and java.lang.reflect.Proxy for a > similar purpose, hoping that method declaration order matches > reflection order (not a good idea, I know). As far as I can see, the > proxy mechanism does not perform a module encapsulation check and can > create instaces at points where a regular class declaration with an > implements clause could not reference to the interface. Records would > be a better replacement because they provide ordering of components. > > > If you use an abstract deconstructors/pattern method, you get the declaration order > > interface Row { > abstract deconstructor (String name, int index) Row(); // or a similar syntax > } > > ... > Row(var name, var index) = csv.readRow(); > // use name and index here > > and i suppose that j.l.r.Proxy will be updated to implement such pattern. > > > Is this already under discussion somewhere? I've seen some references > to generalizing pattern matching to custom types, but nothing along > what you describe. > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Dec 9 18:45:11 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 9 Dec 2024 13:45:11 -0500 Subject: Constructing records through reflection and module restrictions In-Reply-To: References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> <87r06if76t.fsf@mid.deneb.enyo.de> Message-ID: <876c222f-0c90-44c7-ba3b-d5f1f5280cf7@oracle.com> The `opens` clause of a module descriptor indeed can be qualified, just as the exports clause can: ModuleDirective: ??? requires {RequiresModifier} ModuleName ; ??? exports PackageName [to ModuleName {, ModuleName}] ; ??? opens PackageName [to ModuleName {, ModuleName}] ; ??? uses TypeName ; ??? provides TypeName with TypeName {, TypeName} ; On 12/9/2024 1:22 PM, Olexandr Rotan wrote: > > Little of topic here, but what I was lacking with opening is opens * > to X (similar to exports * to X). For example, I want my module to be > open to code that I trust like spring framework, but not accessible to > some 3rd party API wrappers. Something like this would be really > helpful in situations when working with sensitive user data, because > otherwise you either have to give up access control using open module > or open packages one by one to each module which is virtually > unmaintainable. > Putting everything "open" is not really an option since like 95% of > code has to be open to reflection if working with IoC containers and ORM`s > > > On Mon, Dec 9, 2024, 19:07 Brian Goetz wrote: > > There is a better approach than passing around the Lookup (which > requires everyone to coordinate around the Lookup capability): use > open modules.? THe concept of "open module" was designed for > exactly this purpose: to allow packages to be "exported for > reflection" so that frameworks can reflect over them more > liberally than bytecode linkage would permit.? If you put your > domain objects in a package that is opened (either to the > framework, or to everyone), no need to play games with Lookup. > > > On 12/8/2024 11:52 AM, Florian Weimer wrote: >> * Remi Forax: >> >>>> Syntax-wise, it is very tempting to use this with very localized >>>> record types for various kinds of custom deserialization scenarios. >>>> For example, to read a CSV file with two colums, something like this >>>> could be used: >>>> >>>> record Row(String name, int index) {} >>>> var csv = CSVReader.newReader(r, Row.class); >>>> while (true) { >>>> var row = csv.readRow(); >>>> if (row == null) >>>> break; >>>> // Use the row variable. >>>> ... >>>> } >>>> >>>> But it would equally work for SQL result set rows, binary structures, >>>> and so on. >>> Why not sending the lookup object here : >>> >>> var csv = CSVReader.newReader(r, Row.class, MethodHandles.lookup()); >> Thanks. Not surpringly, this works for constructor access. It should >> help with using defineHiddenClass() as well if I read the >> documentation correctly (although maybe I can get what I want just >> using method handles). Syntax-wise, I think it's okay, although it >> will certainly look like magic to newcomers if this programming >> pattern ever catches on (and similarly in other APIs that use >> reflective access behind the covers). But from a conceptual >> perspective, it's really clear. >> >> It appears that MethodHandles.lookup() uses an intrisified >> getCallerClass(), so it's probably not necessary to turn this into >> MethodHandles::lookup, to the lookup when it is not needed. >> >>>> I think some people use interfaces and java.lang.reflect.Proxy for a >>>> similar purpose, hoping that method declaration order matches >>>> reflection order (not a good idea, I know). As far as I can see, the >>>> proxy mechanism does not perform a module encapsulation check and can >>>> create instaces at points where a regular class declaration with an >>>> implements clause could not reference to the interface. Records would >>>> be a better replacement because they provide ordering of components. >>> If you use an abstract deconstructors/pattern method, you get the declaration order >>> >>> interface Row { >>> abstract deconstructor (String name, int index) Row(); // or a similar syntax >>> } >>> >>> ... >>> Row(var name, var index) = csv.readRow(); >>> // use name and index here >>> >>> and i suppose that j.l.r.Proxy will be updated to implement such pattern. >> Is this already under discussion somewhere? I've seen some references >> to generalizing pattern matching to custom types, but nothing along >> what you describe. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rleach at rleach.id.au Tue Dec 10 04:38:24 2024 From: rleach at rleach.id.au (Ryan Leach) Date: Tue, 10 Dec 2024 15:08:24 +1030 Subject: Constructing records through reflection and module restrictions In-Reply-To: <1689465778.17175986.1733675770477.JavaMail.zimbra@univ-eiffel.fr> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <628e33c3-7591-4d48-b2d3-b170d1c61c64@oracle.com> <87v7vufbog.fsf@mid.deneb.enyo.de> <0a949c7d-a800-4e7f-844e-36694565027c@oracle.com> <1689465778.17175986.1733675770477.JavaMail.zimbra@univ-eiffel.fr> Message-ID: The way I've seen records adopted and used, seem pretty far removed from Tuples, so don't really understand why you are in support of making them more Tuple-like Remi. I suspect we'll see true Tuples being introduced long before records are considered to be turned into Tuples. Not that I suspect that's particularly likely. On Mon, 9 Dec 2024, 3:07?am Remi Forax, wrote: > > > ------------------------------ > > *From: *"Brian Goetz" > *To: *"Florian Weimer" > *Cc: *"amber-dev" > *Sent: *Sunday, December 8, 2024 4:50:43 PM > *Subject: *Re: Constructing records through reflection and module > restrictions > > Sure, there are other ways we could have designed the language. Tuples > are structural types, which means they are not declared, but instead spring > when the type constructor is applied to other (necessarily accessible) > types. This means there is no need for access control, since anyone who > can access T and U can "summon" the type `tuple`. (We have this for > arrays already -- which is already a significant source of irregularity in > the language, so we chose not to emulate that.) > > But, we chose to lean into Java's class-based, nominal type system. > Making special exceptions "because it's like a tuple" is surely convenience > in some cases, but makes the language more complicated to reason about > overall. > > > We have made an exception for lambdas. > > There is something special with tuples, most of my students now learn > programming with Python as first langage, so there are used to use tuples > as an element of design. > As an example, when students start Java, we have a course to explain that > Java has no tuples and the difference between a record and a tuple. > > Another example, currently, this is the time of the year where we are > doing the advent of code, students can choose the langage they want, most > of the undergraduate students choose Python. > When asked why, having tuples is the most cited feature, and it makes > sense given the kind of problems of the advent of code. > > I think we will have to fix this in Java at some point, not now, perhaps > even not us, but exactly like we did not need lambdas because we had inner > classes, not having tuples will be seen increasingly as a Java problem. > > regards, > R?mi > > NB: For graduate students, most of them are using Java for the advent of > code, but i suppose this is a kind of Stockholm syndrome reaction because > they are using Java in most of their courses (concurrency, android, http > server, design pattern, spring, etc). > > > > > On 12/8/2024 10:15 AM, Florian Weimer wrote: > > It's the syntactic overhead. The attractiveness of this pattern is > that's it's a clear and concise notation for this type of > deserialization. Creating a public type for it in a suitable package > sort of breaks that. > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ethan at mccue.dev Tue Dec 10 06:35:10 2024 From: ethan at mccue.dev (Ethan McCue) Date: Tue, 10 Dec 2024 15:35:10 +0900 Subject: Constructing records through reflection and module restrictions In-Reply-To: <1689465778.17175986.1733675770477.JavaMail.zimbra@univ-eiffel.fr> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <628e33c3-7591-4d48-b2d3-b170d1c61c64@oracle.com> <87v7vufbog.fsf@mid.deneb.enyo.de> <0a949c7d-a800-4e7f-844e-36694565027c@oracle.com> <1689465778.17175986.1733675770477.JavaMail.zimbra@univ-eiffel.fr> Message-ID: I'd wager the feature being missed in those cases is in-place destructing, less so anonymous components. On Mon, Dec 9, 2024, 2:40 AM Remi Forax wrote: > > > ------------------------------ > > *From: *"Brian Goetz" > *To: *"Florian Weimer" > *Cc: *"amber-dev" > *Sent: *Sunday, December 8, 2024 4:50:43 PM > *Subject: *Re: Constructing records through reflection and module > restrictions > > Sure, there are other ways we could have designed the language. Tuples > are structural types, which means they are not declared, but instead spring > when the type constructor is applied to other (necessarily accessible) > types. This means there is no need for access control, since anyone who > can access T and U can "summon" the type `tuple`. (We have this for > arrays already -- which is already a significant source of irregularity in > the language, so we chose not to emulate that.) > > But, we chose to lean into Java's class-based, nominal type system. > Making special exceptions "because it's like a tuple" is surely convenience > in some cases, but makes the language more complicated to reason about > overall. > > > We have made an exception for lambdas. > > There is something special with tuples, most of my students now learn > programming with Python as first langage, so there are used to use tuples > as an element of design. > As an example, when students start Java, we have a course to explain that > Java has no tuples and the difference between a record and a tuple. > > Another example, currently, this is the time of the year where we are > doing the advent of code, students can choose the langage they want, most > of the undergraduate students choose Python. > When asked why, having tuples is the most cited feature, and it makes > sense given the kind of problems of the advent of code. > > I think we will have to fix this in Java at some point, not now, perhaps > even not us, but exactly like we did not need lambdas because we had inner > classes, not having tuples will be seen increasingly as a Java problem. > > regards, > R?mi > > NB: For graduate students, most of them are using Java for the advent of > code, but i suppose this is a kind of Stockholm syndrome reaction because > they are using Java in most of their courses (concurrency, android, http > server, design pattern, spring, etc). > > > > > On 12/8/2024 10:15 AM, Florian Weimer wrote: > > It's the syntactic overhead. The attractiveness of this pattern is > that's it's a clear and concise notation for this type of > deserialization. Creating a public type for it in a suitable package > sort of breaks that. > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Tue Dec 10 10:00:57 2024 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Tue, 10 Dec 2024 11:00:57 +0100 (CET) Subject: Constructing records through reflection and module restrictions In-Reply-To: References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <628e33c3-7591-4d48-b2d3-b170d1c61c64@oracle.com> <87v7vufbog.fsf@mid.deneb.enyo.de> <0a949c7d-a800-4e7f-844e-36694565027c@oracle.com> <1689465778.17175986.1733675770477.JavaMail.zimbra@univ-eiffel.fr> Message-ID: <1055813512.18413861.1733824857389.JavaMail.zimbra@univ-eiffel.fr> > From: "Ethan McCue" > I'd wager the feature being missed in those cases is in-place destructing, less > so anonymous components. > From: "Ryan Leach" > The way I've seen records adopted and used, seem pretty far removed from Tuples, > so don't really understand why you are in support of making them more > Tuple-like Remi. I suspect we'll see true Tuples being introduced long before > records are considered to be turned into Tuples. Not that I suspect that's > particularly likely. yes, i'm not arguying that records should be tuples, only that for a lot of my students, they see tuples are a building block and Java is missing that. As Ethan said, in-place structuring/destructing is another name for tuples (with named components). By examples: (int min, int max) minmax(int a, int b) { return (Math.min(a, b), Math.max(a, b)); } void main() { var (min, max) = minmax(7, 3); // or var result = minmax(...(7, 3)); // with a spread operator } As Brian said, the main issue here is that those things are structural typed, not nominally typed. R?mi > On Mon, 9 Dec 2024, 3:07 am Remi Forax, < [ mailto:forax at univ-mlv.fr | > forax at univ-mlv.fr ] > wrote: >>> From: "Brian Goetz" < [ mailto:brian.goetz at oracle.com | brian.goetz at oracle.com ] >>> > >>> To: "Florian Weimer" < [ mailto:fw at deneb.enyo.de | fw at deneb.enyo.de ] > >>> Cc: "amber-dev" < [ mailto:amber-dev at openjdk.org | amber-dev at openjdk.org ] > >>> Sent: Sunday, December 8, 2024 4:50:43 PM >>> Subject: Re: Constructing records through reflection and module restrictions >>> Sure, there are other ways we could have designed the language. Tuples are >>> structural types, which means they are not declared, but instead spring when >>> the type constructor is applied to other (necessarily accessible) types. This >>> means there is no need for access control, since anyone who can access T and U >>> can "summon" the type `tuple`. (We have this for arrays already -- which >>> is already a significant source of irregularity in the language, so we chose >>> not to emulate that.) >>> But, we chose to lean into Java's class-based, nominal type system. Making >>> special exceptions "because it's like a tuple" is surely convenience in some >>> cases, but makes the language more complicated to reason about overall. >> We have made an exception for lambdas. >> There is something special with tuples, most of my students now learn >> programming with Python as first langage, so there are used to use tuples as an >> element of design. >> As an example, when students start Java, we have a course to explain that Java >> has no tuples and the difference between a record and a tuple. >> Another example, currently, this is the time of the year where we are doing the >> advent of code, students can choose the langage they want, most of the >> undergraduate students choose Python. >> When asked why, having tuples is the most cited feature, and it makes sense >> given the kind of problems of the advent of code. >> I think we will have to fix this in Java at some point, not now, perhaps even >> not us, but exactly like we did not need lambdas because we had inner classes, >> not having tuples will be seen increasingly as a Java problem. >> regards, >> R?mi >> NB: For graduate students, most of them are using Java for the advent of code, >> but i suppose this is a kind of Stockholm syndrome reaction because they are >> using Java in most of their courses (concurrency, android, http server, design >> pattern, spring, etc). >>> On 12/8/2024 10:15 AM, Florian Weimer wrote: >>>> It's the syntactic overhead. The attractiveness of this pattern is >>>> that's it's a clear and concise notation for this type of >>>> deserialization. Creating a public type for it in a suitable package >>>> sort of breaks that. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jean-noel.rouvignac at pingidentity.com Tue Dec 10 16:10:57 2024 From: jean-noel.rouvignac at pingidentity.com (=?UTF-8?Q?Jean=2DNo=C3=ABl_Rouvignac_=28ForgeRock=29?=) Date: Tue, 10 Dec 2024 17:10:57 +0100 Subject: Enum: difference of behaviour between exhaustive switch vs. using default: Message-ID: Hello amber-dev experts! I am modernizing our codebase by making it use enhanced / exhaustive switches. In several places, I replaced `default: ` by `case THE_ONLY_UNUSED_ENUM_VALUE:`, except that I am hitting an unexpected difference in behaviour, at least from my point of view. I have reduced the code to the following reproducer (tested on the https://dev.java/playground/), where `main1()` compiles, but `main2()` does not. And yet, I am under the impression both should be equivalent? What do you think? Thanks a lot. import java.io.IOException; class Main { public enum Action { IGNORE, REJECT } public static void main(String[] args) { main1(); main2(); } private static void main1() { String s; try { s = getValue(); } catch (IOException e) { switch (getAction()) { case IGNORE: return; default: throw new RuntimeException("REJECTED"); } } System.out.println(s); } private static void main2() { String s; try { s = getValue(); } catch (IOException e) { switch (getAction()) { case IGNORE: return; case REJECT: // <------------------- Fails compilation throw new RuntimeException("REJECTED"); } } System.out.println(s); // <------- Main.java:40: error: variable s might not have been initialized } static Action getAction() { return Action.IGNORE; } static String getValue() throws IOException { return "SUCCESS"; } } -- _CONFIDENTIALITY NOTICE: This email may contain confidential and privileged material for the sole use of the intended recipient(s). Any review, use, distribution or disclosure by others is strictly prohibited.? If you have received this communication in error, please notify the sender immediately by e-mail and delete the message and any file attachments from your computer. Thank you._ -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Tue Dec 10 17:57:02 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Tue, 10 Dec 2024 11:57:02 -0600 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <83a9fa5b-69c1-47cd-bf2a-c49f16cda89f@oracle.com> <7c968acb-6db7-4a87-8b26-93f4f72050bf@oracle.com> <448f92ea-b103-4292-ae70-081ef71b3465@oracle.com> <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: On Fri, Oct 25, 2024 at 10:02?AM Archie Cobbs wrote: > Is there some quasi-consensus to go forward with this idea for fixing > basic for() loops? > (Hmm, nobody responded yes and nobody responded no...) Now that JDK 24 is out of the way, I'd like to get some kind of final adjudication on whether to continue pursuing this idea from this list. If everyone is good with doing this then I'm happy to continue working on it, otherwise I'm happy to shelve it. I would just like to tie up the loose end one way or another. To recap: the idea is to allow loop variables declared in basic (old style) for() loops to be captured in the body of the loop as long as they are not reassigned in the body of the loop (but they may be reassigned in the loop step). For example: for (int i = 1; i <= 3; i++) { Runnable r = () -> System.out.println(i); // allow this } There was lots of good discussion and we did narrow down the idea to what's described above. However I'm unclear on whether to now proceed with asking for additional reviews, etc. and don't want to presume. If nobody replies I won't ask again :) FWIW here's what has been drafted so far (all subject to improvement of course): Bug: https://bugs.openjdk.org/browse/JDK-8341782 CSR: https://bugs.openjdk.org/browse/JDK-8341783 JEP: https://bugs.openjdk.org/browse/JDK-8341785 JLS: https://bugs.openjdk.org/browse/JDK-8341786 PR: https://github.com/openjdk/jdk/pull/21415 Thanks, -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From amaembo at gmail.com Tue Dec 10 18:30:40 2024 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 10 Dec 2024 19:30:40 +0100 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <83a9fa5b-69c1-47cd-bf2a-c49f16cda89f@oracle.com> <7c968acb-6db7-4a87-8b26-93f4f72050bf@oracle.com> <448f92ea-b103-4292-ae70-081ef71b3465@oracle.com> <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: Hello! On Tue, Dec 10, 2024, 18:57 Archie Cobbs wrote: > On Fri, Oct 25, 2024 at 10:02?AM Archie Cobbs > wrote: > >> Is there some quasi-consensus to go forward with this idea for fixing >> basic for() loops? >> > > (Hmm, nobody responded yes and nobody responded no...) > Just for the record: I previously said that I don't think we should salvage classic for loop, because it's awful. Instead, we should invest into adding first-class ranges to Java, or at least library support, to be able to write something like for(int i: rangeClosed(1, 3)) { ... } This way, the lambda problem will be solved automatically, and people will get much more readable and much less errorprone way to iterate over integers. I still stick to this point of view. With best regards, Tagir Valeev > Now that JDK 24 is out of the way, I'd like to get some kind of final > adjudication on whether to continue pursuing this idea from this list. > > If everyone is good with doing this then I'm happy to continue working on > it, otherwise I'm happy to shelve it. I would just like to tie up the loose > end one way or another. > > To recap: the idea is to allow loop variables declared in basic (old > style) for() loops to be captured in the body of the loop as long as they > are not reassigned in the body of the loop (but they may be reassigned in > the loop step). For example: > > for (int i = 1; i <= 3; i++) { > Runnable r = () -> System.out.println(i); // allow this > } > > There was lots of good discussion and we did narrow down the idea to > what's described above. However I'm unclear on whether to now proceed with > asking for additional reviews, etc. and don't want to presume. > > If nobody replies I won't ask again :) > > FWIW here's what has been drafted so far (all subject to improvement of > course): > > Bug: https://bugs.openjdk.org/browse/JDK-8341782 > CSR: https://bugs.openjdk.org/browse/JDK-8341783 > JEP: https://bugs.openjdk.org/browse/JDK-8341785 > JLS: https://bugs.openjdk.org/browse/JDK-8341786 > PR: https://github.com/openjdk/jdk/pull/21415 > > Thanks, > -Archie > > -- > Archie L. Cobbs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vab2048 at gmail.com Tue Dec 10 22:52:42 2024 From: vab2048 at gmail.com (Vikram Bakshi) Date: Tue, 10 Dec 2024 22:52:42 +0000 Subject: amber-dev Digest, Vol 94, Issue 15 In-Reply-To: References: Message-ID: Might be off-topic for the mailing list but I thought I would share since it is on topic for the thread. Remi - you might like my library: https://easytuples.github.io/easy-tuples/ It is intended to provide as close to "structural" tuples as I think are possible in Java right now. On a previous thread it was stated that the in-place destructuring will come (nominal de-structuring of course not structural) but is lower priority. See: https://mail.openjdk.org/pipermail/amber-dev/2024-December/009105.html Your example: (int min, int max) minmax(int a, int b) { return (Math.min(a, b), Math.max(a, b)); } void main() { var (min, max) = minmax(7, 3); // or var result = minmax(...(7, 3)); // with a spread operator } Could eventually become: _2 minmax(int a, int b) { return _2.of(Math.min(a,b), Math.max(a,b)); } void main() { _2(var min, var max) pair = minmax(7,3); } (the _2 type is my 'structural' pair tuple in the library I mentioned above) Regards, Vikram On Tue, Dec 10, 2024 at 10:01?AM wrote: > > 2. Re: Constructing records through reflection and module > restrictions (forax at univ-mlv.fr) > > > > Message: 2 > Date: Tue, 10 Dec 2024 11:00:57 +0100 (CET) > From: forax at univ-mlv.fr > To: Ryan Leach , Ethan McCue > Cc: amber-dev > Subject: Re: Constructing records through reflection and module > restrictions > Message-ID: > <1055813512.18413861.1733824857389.JavaMail.zimbra at univ-eiffel.fr> > Content-Type: text/plain; charset="utf-8" > > > From: "Ethan McCue" > > > I'd wager the feature being missed in those cases is in-place > destructing, less > > so anonymous components. > > > From: "Ryan Leach" > > > The way I've seen records adopted and used, seem pretty far removed from > Tuples, > > so don't really understand why you are in support of making them more > > Tuple-like Remi. I suspect we'll see true Tuples being introduced long > before > > records are considered to be turned into Tuples. Not that I suspect > that's > > particularly likely. > > yes, i'm not arguying that records should be tuples, only that for a lot > of my students, they see tuples are a building block and Java is missing > that. > > As Ethan said, in-place structuring/destructing is another name for tuples > (with named components). > > By examples: > (int min, int max) minmax(int a, int b) { > return (Math.min(a, b), Math.max(a, b)); > } > > void main() { > var (min, max) = minmax(7, 3); > // or > var result = minmax(...(7, 3)); // with a spread operator > } > > As Brian said, the main issue here is that those things are structural > typed, not nominally typed. > > R?mi > > > On Mon, 9 Dec 2024, 3:07 am Remi Forax, < [ mailto:forax at univ-mlv.fr | > > forax at univ-mlv.fr ] > wrote: > > >>> From: "Brian Goetz" < [ mailto:brian.goetz at oracle.com | > brian.goetz at oracle.com ] > >>> > > >>> To: "Florian Weimer" < [ mailto:fw at deneb.enyo.de | fw at deneb.enyo.de ] > > > >>> Cc: "amber-dev" < [ mailto:amber-dev at openjdk.org | > amber-dev at openjdk.org ] > > >>> Sent: Sunday, December 8, 2024 4:50:43 PM > >>> Subject: Re: Constructing records through reflection and module > restrictions > > >>> Sure, there are other ways we could have designed the language. Tuples > are > >>> structural types, which means they are not declared, but instead > spring when > >>> the type constructor is applied to other (necessarily accessible) > types. This > >>> means there is no need for access control, since anyone who can access > T and U > >>> can "summon" the type `tuple`. (We have this for arrays already > -- which > >>> is already a significant source of irregularity in the language, so we > chose > >>> not to emulate that.) > > >>> But, we chose to lean into Java's class-based, nominal type system. > Making > >>> special exceptions "because it's like a tuple" is surely convenience > in some > >>> cases, but makes the language more complicated to reason about overall. > >> We have made an exception for lambdas. > > >> There is something special with tuples, most of my students now learn > >> programming with Python as first langage, so there are used to use > tuples as an > >> element of design. > >> As an example, when students start Java, we have a course to explain > that Java > >> has no tuples and the difference between a record and a tuple. > > >> Another example, currently, this is the time of the year where we are > doing the > >> advent of code, students can choose the langage they want, most of the > >> undergraduate students choose Python. > >> When asked why, having tuples is the most cited feature, and it makes > sense > >> given the kind of problems of the advent of code. > > >> I think we will have to fix this in Java at some point, not now, > perhaps even > >> not us, but exactly like we did not need lambdas because we had inner > classes, > >> not having tuples will be seen increasingly as a Java problem. > > >> regards, > >> R?mi > > >> NB: For graduate students, most of them are using Java for the advent > of code, > >> but i suppose this is a kind of Stockholm syndrome reaction because > they are > >> using Java in most of their courses (concurrency, android, http server, > design > >> pattern, spring, etc). > > >>> On 12/8/2024 10:15 AM, Florian Weimer wrote: > > >>>> It's the syntactic overhead. The attractiveness of this pattern is > >>>> that's it's a clear and concise notation for this type of > >>>> deserialization. Creating a public type for it in a suitable package > >>>> sort of breaks that. > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: < > https://mail.openjdk.org/pipermail/amber-dev/attachments/20241210/bf0ddbb3/attachment.htm > > > > End of amber-dev Digest, Vol 94, Issue 15 > ***************************************** > -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Wed Dec 11 02:43:58 2024 From: davidalayachew at gmail.com (David Alayachew) Date: Tue, 10 Dec 2024 21:43:58 -0500 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <83a9fa5b-69c1-47cd-bf2a-c49f16cda89f@oracle.com> <7c968acb-6db7-4a87-8b26-93f4f72050bf@oracle.com> <448f92ea-b103-4292-ae70-081ef71b3465@oracle.com> <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: I am in the camp of "do it all, or don't do it at all." Either this "quiescent" functionality elevates past for-loops and becomes available to ALL local variables, or this just shouldn't be done at all. For-loops (even loops in general) happen to be the most obvious pain point, but they certainly aren't the only one. That said, even if we apply this quiescent functionality to all local variables, we would only be scratching the surface of the REAL problem -- CORRECTLY outlining when and where it is TRULY SAFE to use a variable's value. The entire reason that this feature is being considered is because WE KNOW that we are being safe, but the compiler doesn't have enough info to know. The rules for safety do not align with what is TRULY SAFE. So much so, that even beginner's to this language can see the excessiveness of the rules here. Here is an example of what I mean when I say we are only scratching the surface. https://stackoverflow.com/questions/75072937/why-does-my-lambda-get-illegal-forward-reference-but-my-anonymous-class-does-no This also bumps shoulders with your "before super()" work Archie. We intuitively "know" that something like this should be possible, but the language doesn't expose any way of doing this without some level of indirection, duplication, or assignment after the fact. Just like a dummy variable for for-loops. On Tue, Dec 10, 2024 at 1:31?PM Tagir Valeev wrote: > Hello! > > > > On Tue, Dec 10, 2024, 18:57 Archie Cobbs wrote: > >> On Fri, Oct 25, 2024 at 10:02?AM Archie Cobbs >> wrote: >> >>> Is there some quasi-consensus to go forward with this idea for fixing >>> basic for() loops? >>> >> >> (Hmm, nobody responded yes and nobody responded no...) >> > > Just for the record: I previously said that I don't think we should > salvage classic for loop, because it's awful. Instead, we should invest > into adding first-class ranges to Java, or at least library support, to be > able to write something like > > for(int i: rangeClosed(1, 3)) { > ... > } > > This way, the lambda problem will be solved automatically, and people will > get much more readable and much less errorprone way to iterate over > integers. > > I still stick to this point of view. > > With best regards, > Tagir Valeev > > >> Now that JDK 24 is out of the way, I'd like to get some kind of final >> adjudication on whether to continue pursuing this idea from this list. >> >> If everyone is good with doing this then I'm happy to continue working on >> it, otherwise I'm happy to shelve it. I would just like to tie up the loose >> end one way or another. >> >> To recap: the idea is to allow loop variables declared in basic (old >> style) for() loops to be captured in the body of the loop as long as they >> are not reassigned in the body of the loop (but they may be reassigned in >> the loop step). For example: >> >> for (int i = 1; i <= 3; i++) { >> Runnable r = () -> System.out.println(i); // allow this >> } >> >> There was lots of good discussion and we did narrow down the idea to >> what's described above. However I'm unclear on whether to now proceed with >> asking for additional reviews, etc. and don't want to presume. >> >> If nobody replies I won't ask again :) >> >> FWIW here's what has been drafted so far (all subject to improvement of >> course): >> >> Bug: https://bugs.openjdk.org/browse/JDK-8341782 >> CSR: https://bugs.openjdk.org/browse/JDK-8341783 >> JEP: https://bugs.openjdk.org/browse/JDK-8341785 >> JLS: https://bugs.openjdk.org/browse/JDK-8341786 >> PR: https://github.com/openjdk/jdk/pull/21415 >> >> Thanks, >> -Archie >> >> -- >> Archie L. Cobbs >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From kasperni at gmail.com Wed Dec 11 05:19:16 2024 From: kasperni at gmail.com (Kasper Nielsen) Date: Wed, 11 Dec 2024 10:49:16 +0530 Subject: Constructing records through reflection and module restrictions In-Reply-To: <876c222f-0c90-44c7-ba3b-d5f1f5280cf7@oracle.com> References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> <87r06if76t.fsf@mid.deneb.enyo.de> <876c222f-0c90-44c7-ba3b-d5f1f5280cf7@oracle.com> Message-ID: On Tue, 10 Dec 2024 at 00:41, Brian Goetz wrote: > > The `opens` clause of a module descriptor indeed can be qualified, just as the exports clause can: Qualified module opens is one of those few features in modern Java that, in my opinion, didn't turn out so well. * It got the granularity wrong It should have operated on the whole module instead of individual packages. "opens [to ModuleName {, ModuleName}]" instead of "opens PackageName [to ModuleName {, ModuleName}]" Qualified module exports at the package level work fine because by the time you?re ready to start exporting your packages, your module is "mature," and you have a good idea of its final layout. It is just the other way around with qualified opens. You need to start using it when you create your first class that needs reflective access. You probably have no idea about what packages you are going to create, and you move things around a lot initially. Having to constantly modify the module declaration in this initial phase really gets in the way of the development process. Had it just been a single "opens to spring.framework, hibernate.framework" statement in your module declaration you would have been fine. But package level granularity is just too much bookkeeping, especially in the "exploration" phase of a module. * Not enforceable at runtime With a little Classfile magic anyone can get access to every other package in a module if they have access to just a single package. You simply create a new class in the package you have access to. This new class then creates and returns a lookup object that has module access to the rest of the packages in the module. * Breaks Integrity The previous point really does not fit well with all the great work being done within "Integrity by Default". If I have this statement in my module declaration "opens com.acme.publicinfo to some-module", I would be very surprised to learn that this also gives to some-module for my "com.acme.secrets" package and everything else in the module. The best option would probably be to start adding warnings when people use qualified module opens to tell them that the operation does not do what they expect. And then add a "opens [to ModuleName {, ModuleName}]" option. Will need some small changes to java.lang.Module. And worst case an additional flag in the classfile. I really do think that a module declaration option for opens still has its merits over using a Lookup object. It is just a lot easier to explain that you have a single place (a module declaration) to control everything. Instead of needing to explain both module declarations and Lookup objects. /Kasper From gavin.bierman at oracle.com Wed Dec 11 12:20:15 2024 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Wed, 11 Dec 2024 12:20:15 +0000 Subject: Enum: difference of behaviour between exhaustive switch vs. using default: In-Reply-To: References: Message-ID: Could you file this as a bug, and I will take a look? Thanks, Gavin On 10 Dec 2024, at 16:10, Jean-No?l Rouvignac (ForgeRock) wrote: Hello amber-dev experts! I am modernizing our codebase by making it use enhanced / exhaustive switches. In several places, I replaced `default: ` by `case THE_ONLY_UNUSED_ENUM_VALUE:`, except that I am hitting an unexpected difference in behaviour, at least from my point of view. I have reduced the code to the following reproducer (tested on the https://dev.java/playground/), where `main1()` compiles, but `main2()` does not. And yet, I am under the impression both should be equivalent? What do you think? Thanks a lot. import java.io.IOException; class Main { public enum Action { IGNORE, REJECT } public static void main(String[] args) { main1(); main2(); } private static void main1() { String s; try { s = getValue(); } catch (IOException e) { switch (getAction()) { case IGNORE: return; default: throw new RuntimeException("REJECTED"); } } System.out.println(s); } private static void main2() { String s; try { s = getValue(); } catch (IOException e) { switch (getAction()) { case IGNORE: return; case REJECT: // <------------------- Fails compilation throw new RuntimeException("REJECTED"); } } System.out.println(s); // <------- Main.java:40: error: variable s might not have been initialized } static Action getAction() { return Action.IGNORE; } static String getValue() throws IOException { return "SUCCESS"; } } CONFIDENTIALITY NOTICE: This email may contain confidential and privileged material for the sole use of the intended recipient(s). Any review, use, distribution or disclosure by others is strictly prohibited. If you have received this communication in error, please notify the sender immediately by e-mail and delete the message and any file attachments from your computer. Thank you. -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Wed Dec 11 12:44:38 2024 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 11 Dec 2024 13:44:38 +0100 (CET) Subject: Enum: difference of behaviour between exhaustive switch vs. using default: In-Reply-To: References: Message-ID: <1251049146.19372898.1733921078225.JavaMail.zimbra@univ-eiffel.fr> Hello, I think it can be reduced to public enum Action { IGNORE , REJECT } private static void bad () { String s ; switch ( getAction ()) { case IGNORE : s = "foo" ; break ; case REJECT : throw new RuntimeException( "REJECTED" ); }; System . out .println( s ); // <------- variable s might not have been initialized } private static void ok () { String s = switch ( getAction ()) { case IGNORE : yield "foo" ; case REJECT : throw new RuntimeException( "REJECTED" ); }; System . out .println( s ); // ok ! } so there is a bug in DA/DU rules and the workaround is to use a switch expression. R?mi > From: "Gavin Bierman" > To: "Jean-No?l Rouvignac (ForgeRock)" > Cc: "amber-dev" > Sent: Wednesday, December 11, 2024 1:20:15 PM > Subject: Re: Enum: difference of behaviour between exhaustive switch vs. using > default: > Could you file this as a bug, and I will take a look? > Thanks, > Gavin >> On 10 Dec 2024, at 16:10, Jean-No?l Rouvignac (ForgeRock) >> wrote: >> Hello amber-dev experts! >> I am modernizing our codebase by making it use enhanced / exhaustive switches. >> In several places, I replaced `default: ` by `case THE_ONLY_UNUSED_ENUM_VALUE:`, >> except that I am hitting an unexpected difference in behaviour, at least from >> my point of view. >> I have reduced the code to the following reproducer (tested on the [ >> https://dev.java/playground/ | >> https://dev.java/playground/ ] ), where `main1()` compiles, but `main2()` does >> not. And yet, I am under the impression both should be equivalent? >> What do you think? >> Thanks a lot. >> import java.io.IOException; >> class Main { >> public enum Action { IGNORE, REJECT } >> public static void main(String[] args) { >> main1(); >> main2(); >> } >> private static void main1() { >> String s; >> try { >> s = getValue(); >> } catch (IOException e) { >> switch (getAction()) { >> case IGNORE: >> return; >> default: >> throw new RuntimeException("REJECTED"); >> } >> } >> System.out.println(s); >> } >> private static void main2() { >> String s; >> try { >> s = getValue(); >> } catch (IOException e) { >> switch (getAction()) { >> case IGNORE: >> return; >> case REJECT: // <------------------- Fails compilation >> throw new RuntimeException("REJECTED"); >> } >> } >> System.out.println(s); // <------- Main.java:40: error: variable s might not >> have been initialized >> } >> static Action getAction() { >> return Action.IGNORE; >> } >> static String getValue() throws IOException { >> return "SUCCESS"; >> } >> } >> CONFIDENTIALITY NOTICE: This email may contain confidential and privileged >> material for the sole use of the intended recipient(s). Any review, use, >> distribution or disclosure by others is strictly prohibited. If you have >> received this communication in error, please notify the sender immediately by >> e-mail and delete the message and any file attachments from your computer. >> Thank you. -------------- next part -------------- An HTML attachment was scrubbed... URL: From angelos.bimpoudis at oracle.com Wed Dec 11 14:05:51 2024 From: angelos.bimpoudis at oracle.com (Angelos Bimpoudis) Date: Wed, 11 Dec 2024 14:05:51 +0000 Subject: Enum: difference of behaviour between exhaustive switch vs. using default: In-Reply-To: <1251049146.19372898.1733921078225.JavaMail.zimbra@univ-eiffel.fr> References: <1251049146.19372898.1733921078225.JavaMail.zimbra@univ-eiffel.fr> Message-ID: Filed it here: https://bugs.openjdk.org/browse/JDK-8345997 Thank you for reaching out! Thx Remi for the minimized example as well. ________________________________ From: amber-dev on behalf of Remi Forax Sent: 11 December 2024 13:44 To: Gavin Bierman Cc: Jean-No?l Rouvignac (ForgeRock) ; amber-dev Subject: Re: Enum: difference of behaviour between exhaustive switch vs. using default: Hello, I think it can be reduced to public enum Action { IGNORE, REJECT } private static void bad() { String s; switch (getAction()) { case IGNORE: s = "foo"; break; case REJECT: throw new RuntimeException("REJECTED"); }; System.out.println(s); // <------- variable s might not have been initialized } private static void ok() { String s = switch (getAction()) { case IGNORE: yield "foo"; case REJECT: throw new RuntimeException("REJECTED"); }; System.out.println(s); // ok ! } so there is a bug in DA/DU rules and the workaround is to use a switch expression. R?mi ________________________________ From: "Gavin Bierman" To: "Jean-No?l Rouvignac (ForgeRock)" Cc: "amber-dev" Sent: Wednesday, December 11, 2024 1:20:15 PM Subject: Re: Enum: difference of behaviour between exhaustive switch vs. using default: Could you file this as a bug, and I will take a look? Thanks, Gavin On 10 Dec 2024, at 16:10, Jean-No?l Rouvignac (ForgeRock) wrote: Hello amber-dev experts! I am modernizing our codebase by making it use enhanced / exhaustive switches. In several places, I replaced `default: ` by `case THE_ONLY_UNUSED_ENUM_VALUE:`, except that I am hitting an unexpected difference in behaviour, at least from my point of view. I have reduced the code to the following reproducer (tested on the https://dev.java/playground/), where `main1()` compiles, but `main2()` does not. And yet, I am under the impression both should be equivalent? What do you think? Thanks a lot. import java.io.IOException; class Main { public enum Action { IGNORE, REJECT } public static void main(String[] args) { main1(); main2(); } private static void main1() { String s; try { s = getValue(); } catch (IOException e) { switch (getAction()) { case IGNORE: return; default: throw new RuntimeException("REJECTED"); } } System.out.println(s); } private static void main2() { String s; try { s = getValue(); } catch (IOException e) { switch (getAction()) { case IGNORE: return; case REJECT: // <------------------- Fails compilation throw new RuntimeException("REJECTED"); } } System.out.println(s); // <------- Main.java:40: error: variable s might not have been initialized } static Action getAction() { return Action.IGNORE; } static String getValue() throws IOException { return "SUCCESS"; } } CONFIDENTIALITY NOTICE: This email may contain confidential and privileged material for the sole use of the intended recipient(s). Any review, use, distribution or disclosure by others is strictly prohibited. If you have received this communication in error, please notify the sender immediately by e-mail and delete the message and any file attachments from your computer. Thank you. -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.1993grajales at gmail.com Wed Dec 11 15:58:40 2024 From: david.1993grajales at gmail.com (david Grajales) Date: Wed, 11 Dec 2024 10:58:40 -0500 Subject: anonymous records as an implementation for tuples in Java Message-ID: 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() for passing them as arguments to methods it could be something like this. void foo(Tuple 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. -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed Dec 11 16:22:41 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 11 Dec 2024 11:22:41 -0500 Subject: anonymous records as an implementation for tuples in Java In-Reply-To: References: Message-ID: 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 () > > for passing them as arguments to methods it could be something like this. > > void foo(Tuple 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. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.1993grajales at gmail.com Wed Dec 11 16:53:21 2024 From: david.1993grajales at gmail.com (david Grajales) Date: Wed, 11 Dec 2024 11:53:21 -0500 Subject: anonymous records as an implementation for tuples in Java In-Reply-To: References: Message-ID: Thank you Brian. As always you have a talent to explain things clearly. Yes I supposed it would be far more complicated than meets the eye from outside. (That's usually the case) Thanks for answering. El mi?, 11 de dic de 2024, 11:22?a. m., Brian Goetz escribi?: > 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() > > for passing them as arguments to methods it could be something like this. > > void foo(Tuple 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. > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From redio.development at gmail.com Wed Dec 11 16:59:33 2024 From: redio.development at gmail.com (Red IO) Date: Wed, 11 Dec 2024 17:59:33 +0100 Subject: anonymous records as an implementation for tuples in Java In-Reply-To: References: Message-ID: 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 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() > > for passing them as arguments to methods it could be something like this. > > void foo(Tuple 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. > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed Dec 11 17:27:13 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 11 Dec 2024 12:27:13 -0500 Subject: anonymous records as an implementation for tuples in Java In-Reply-To: References: Message-ID: <6f0d9ba5-f4c2-441d-a4b0-1f7fa1b456c9@oracle.com> 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 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 >> () >> >> for passing them as arguments to methods it could be something >> like this. >> >> void foo(Tuple 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. >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jean-noel.rouvignac at pingidentity.com Wed Dec 11 17:43:13 2024 From: jean-noel.rouvignac at pingidentity.com (=?UTF-8?Q?Jean=2DNo=C3=ABl_Rouvignac?=) Date: Wed, 11 Dec 2024 18:43:13 +0100 Subject: Enum: difference of behaviour between exhaustive switch vs. using default: In-Reply-To: References: <1251049146.19372898.1733921078225.JavaMail.zimbra@univ-eiffel.fr> Message-ID: Thank you all! I agree with Remi, the problem no longer exists when using a switch expression. I thought I could not do it with our (obviously more contrived) code, but I have managed to do it in the end. That said, after sending the email, I actually wondered if this problem was actually linked to the use of the "old switch" statement, and a possible lack of understanding of the control flow? I am ready to be told "we cannot fix it because of JLS rule 4.5.6.7" or something like that. Thank you again for taking a look at it, Jean-No?l On Wed, Dec 11, 2024 at 3:05?PM Angelos Bimpoudis < angelos.bimpoudis at oracle.com> wrote: > Filed it here: https://bugs.openjdk.org/browse/JDK-8345997 > > Thank you for reaching out! > Thx Remi for the minimized example as well. > ------------------------------ > *From:* amber-dev on behalf of Remi Forax < > forax at univ-mlv.fr> > *Sent:* 11 December 2024 13:44 > *To:* Gavin Bierman > *Cc:* Jean-No?l Rouvignac (ForgeRock) < > jean-noel.rouvignac at pingidentity.com>; amber-dev > *Subject:* Re: Enum: difference of behaviour between exhaustive switch > vs. using default: > > Hello, > I think it can be reduced to > > public enum Action { IGNORE, REJECT } > > private static void bad() { > String s; > switch (getAction()) { > case IGNORE: > s = "foo"; > break; > case REJECT: > throw new RuntimeException("REJECTED"); > }; > System.out.println(s); // <------- variable s might not have been initialized > } > > private static void ok() { > String s = switch (getAction()) { > case IGNORE: > yield "foo"; > case REJECT: > throw new RuntimeException("REJECTED"); > }; > System.out.println(s); // ok ! > } > > > so there is a bug in DA/DU rules and the workaround is to use a switch > expression. > > R?mi > > ------------------------------ > > *From: *"Gavin Bierman" > *To: *"Jean-No?l Rouvignac (ForgeRock)" < > jean-noel.rouvignac at pingidentity.com> > *Cc: *"amber-dev" > *Sent: *Wednesday, December 11, 2024 1:20:15 PM > *Subject: *Re: Enum: difference of behaviour between exhaustive switch > vs. using default: > > Could you file this as a bug, and I will take a look? > > Thanks, > Gavin > > On 10 Dec 2024, at 16:10, Jean-No?l Rouvignac (ForgeRock) < > jean-noel.rouvignac at pingidentity.com> wrote: > > Hello amber-dev experts! > > I am modernizing our codebase by making it use enhanced / exhaustive > switches. > > In several places, I replaced `default: ` by `case > THE_ONLY_UNUSED_ENUM_VALUE:`, except that I am hitting an unexpected > difference in behaviour, at least from my point of view. > > I have reduced the code to the following reproducer (tested on the > https://dev.java/playground/), where `main1()` compiles, but `main2()` > does not. And yet, I am under the impression both should be equivalent? > > What do you think? > Thanks a lot. > > > > import java.io.IOException; > > class Main { > public enum Action { IGNORE, REJECT } > > public static void main(String[] args) { > main1(); > main2(); > } > > private static void main1() { > String s; > try { > s = getValue(); > } catch (IOException e) { > switch (getAction()) { > case IGNORE: > return; > default: > throw new RuntimeException("REJECTED"); > } > } > > System.out.println(s); > } > > private static void main2() { > String s; > try { > s = getValue(); > } catch (IOException e) { > switch (getAction()) { > case IGNORE: > return; > case REJECT: // <------------------- Fails compilation > throw new RuntimeException("REJECTED"); > } > } > > System.out.println(s); // <------- Main.java:40: error: variable s > might not have been initialized > } > > static Action getAction() { > return Action.IGNORE; > } > > static String getValue() throws IOException { > return "SUCCESS"; > } > } > > > > *CONFIDENTIALITY NOTICE: This email may contain confidential and > privileged material for the sole use of the intended recipient(s). Any > review, use, distribution or disclosure by others is strictly prohibited. > If you have received this communication in error, please notify the sender > immediately by e-mail and delete the message and any file attachments from > your computer. Thank you.* > > > > -- [image: Ping Identity] Jean-Noel Rouvignac Senior Principal Software Engineer jean-noel.rouvignac at pingidentity.com Connect with us: [image: Glassdoor logo] [image: LinkedIn logo] [image: twitter logo] [image: facebook logo] [image: youtube logo] [image: Blog logo] To view our privacy policy, click here To stop receiving these emails, click here -- _CONFIDENTIALITY NOTICE: This email may contain confidential and privileged material for the sole use of the intended recipient(s). Any review, use, distribution or disclosure by others is strictly prohibited.? If you have received this communication in error, please notify the sender immediately by e-mail and delete the message and any file attachments from your computer. Thank you._ -------------- next part -------------- An HTML attachment was scrubbed... URL: From kan.izh at gmail.com Wed Dec 11 17:50:32 2024 From: kan.izh at gmail.com (Anatoly Kupriyanov) Date: Wed, 11 Dec 2024 17:50:32 +0000 Subject: anonymous records as an implementation for tuples in Java In-Reply-To: <6f0d9ba5-f4c2-441d-a4b0-1f7fa1b456c9@oracle.com> References: <6f0d9ba5-f4c2-441d-a4b0-1f7fa1b456c9@oracle.com> Message-ID: 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 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 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 >> >> () >> >> for passing them as arguments to methods it could be something like this. >> >> void foo(Tuple 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: From cushon at google.com Wed Dec 11 17:52:34 2024 From: cushon at google.com (Liam Miller-Cushon) Date: Wed, 11 Dec 2024 09:52:34 -0800 Subject: Enum: difference of behaviour between exhaustive switch vs. using default: In-Reply-To: References: <1251049146.19372898.1733921078225.JavaMail.zimbra@univ-eiffel.fr> Message-ID: I had thought that the difference might be related to the statement not being an 'enhanced' switch statement (JLS 14.11.2), and how non-enhanced switch statements are not required to be exhaustive. 14.11.3 says if no switch label applies, and the switch statement is not enhanced, then it completes normally. So in the case of separate compilation where a new constant is added to the enum after the switch is compiled, the variable wouldn't be DA. Was that the intent here? On Wed, Dec 11, 2024 at 9:43?AM Jean-No?l Rouvignac < jean-noel.rouvignac at pingidentity.com> wrote: > Thank you all! > > I agree with Remi, the problem no longer exists when using a switch > expression. > I thought I could not do it with our (obviously more contrived) code, but > I have managed to do it in the end. > > That said, after sending the email, I actually wondered if this problem > was actually linked to the use of the "old switch" statement, and a > possible lack of understanding of the control flow? > I am ready to be told "we cannot fix it because of JLS rule 4.5.6.7" or > something like that. > > Thank you again for taking a look at it, > Jean-No?l > > > > > On Wed, Dec 11, 2024 at 3:05?PM Angelos Bimpoudis < > angelos.bimpoudis at oracle.com> wrote: > >> Filed it here: https://bugs.openjdk.org/browse/JDK-8345997 >> >> Thank you for reaching out! >> Thx Remi for the minimized example as well. >> ------------------------------ >> *From:* amber-dev on behalf of Remi Forax < >> forax at univ-mlv.fr> >> *Sent:* 11 December 2024 13:44 >> *To:* Gavin Bierman >> *Cc:* Jean-No?l Rouvignac (ForgeRock) < >> jean-noel.rouvignac at pingidentity.com>; amber-dev >> *Subject:* Re: Enum: difference of behaviour between exhaustive switch >> vs. using default: >> >> Hello, >> I think it can be reduced to >> >> public enum Action { IGNORE, REJECT } >> >> private static void bad() { >> String s; >> switch (getAction()) { >> case IGNORE: >> s = "foo"; >> break; >> case REJECT: >> throw new RuntimeException("REJECTED"); >> }; >> System.out.println(s); // <------- variable s might not have been initialized >> } >> >> private static void ok() { >> String s = switch (getAction()) { >> case IGNORE: >> yield "foo"; >> case REJECT: >> throw new RuntimeException("REJECTED"); >> }; >> System.out.println(s); // ok ! >> } >> >> >> so there is a bug in DA/DU rules and the workaround is to use a switch >> expression. >> >> R?mi >> >> ------------------------------ >> >> *From: *"Gavin Bierman" >> *To: *"Jean-No?l Rouvignac (ForgeRock)" < >> jean-noel.rouvignac at pingidentity.com> >> *Cc: *"amber-dev" >> *Sent: *Wednesday, December 11, 2024 1:20:15 PM >> *Subject: *Re: Enum: difference of behaviour between exhaustive switch >> vs. using default: >> >> Could you file this as a bug, and I will take a look? >> >> Thanks, >> Gavin >> >> On 10 Dec 2024, at 16:10, Jean-No?l Rouvignac (ForgeRock) < >> jean-noel.rouvignac at pingidentity.com> wrote: >> >> Hello amber-dev experts! >> >> I am modernizing our codebase by making it use enhanced / exhaustive >> switches. >> >> In several places, I replaced `default: ` by `case >> THE_ONLY_UNUSED_ENUM_VALUE:`, except that I am hitting an unexpected >> difference in behaviour, at least from my point of view. >> >> I have reduced the code to the following reproducer (tested on the >> https://dev.java/playground/), where `main1()` compiles, but `main2()` >> does not. And yet, I am under the impression both should be equivalent? >> >> What do you think? >> Thanks a lot. >> >> >> >> import java.io.IOException; >> >> class Main { >> public enum Action { IGNORE, REJECT } >> >> public static void main(String[] args) { >> main1(); >> main2(); >> } >> >> private static void main1() { >> String s; >> try { >> s = getValue(); >> } catch (IOException e) { >> switch (getAction()) { >> case IGNORE: >> return; >> default: >> throw new RuntimeException("REJECTED"); >> } >> } >> >> System.out.println(s); >> } >> >> private static void main2() { >> String s; >> try { >> s = getValue(); >> } catch (IOException e) { >> switch (getAction()) { >> case IGNORE: >> return; >> case REJECT: // <------------------- Fails compilation >> throw new RuntimeException("REJECTED"); >> } >> } >> >> System.out.println(s); // <------- Main.java:40: error: variable >> s might not have been initialized >> } >> >> static Action getAction() { >> return Action.IGNORE; >> } >> >> static String getValue() throws IOException { >> return "SUCCESS"; >> } >> } >> >> >> >> *CONFIDENTIALITY NOTICE: This email may contain confidential and >> privileged material for the sole use of the intended recipient(s). Any >> review, use, distribution or disclosure by others is strictly prohibited. >> If you have received this communication in error, please notify the sender >> immediately by e-mail and delete the message and any file attachments from >> your computer. Thank you.* >> >> >> >> > > -- > [image: > Ping Identity] > Jean-Noel Rouvignac > Senior Principal Software Engineer > jean-noel.rouvignac at pingidentity.com > > > > > Connect with us: > [image: > Glassdoor logo] > > [image: LinkedIn logo] > > [image: twitter logo] > > [image: facebook logo] > > [image: youtube logo] > > [image: Blog logo] > > To view our privacy policy, click here > > To stop receiving these emails, click here > > > *CONFIDENTIALITY NOTICE: This email may contain confidential and > privileged material for the sole use of the intended recipient(s). Any > review, use, distribution or disclosure by others is strictly prohibited. > If you have received this communication in error, please notify the sender > immediately by e-mail and delete the message and any file attachments from > your computer. Thank you.* -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed Dec 11 17:58:55 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 11 Dec 2024 12:58:55 -0500 Subject: anonymous records as an implementation for tuples in Java In-Reply-To: References: <6f0d9ba5-f4c2-441d-a4b0-1f7fa1b456c9@oracle.com> Message-ID: <5a0ce7ff-e078-48b7-be82-2eb41badb8c4@oracle.com> 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 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 >> 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 >>> () >>> >>> for passing them as arguments to methods it could be >>> something like this. >>> >>> void foo(Tuple 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: From archie.cobbs at gmail.com Wed Dec 11 19:33:21 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Wed, 11 Dec 2024 13:33:21 -0600 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <83a9fa5b-69c1-47cd-bf2a-c49f16cda89f@oracle.com> <7c968acb-6db7-4a87-8b26-93f4f72050bf@oracle.com> <448f92ea-b103-4292-ae70-081ef71b3465@oracle.com> <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: Thanks for the comments. On Tue, Dec 10, 2024 at 8:44?PM David Alayachew wrote: > The entire reason that this feature is being considered is because WE KNOW > that we are being safe, but the compiler doesn't have enough info to know. > I think it's more subtle than that... the compiler often does have enough information, but there are some other reasons trying to extend this to all "quiescent" variables would be tricky. One issue is that the JLS doesn't talk about variables being captured & duplicated - even though we know that's what actually happens in practice. In the JLS there's only one variable. Therefore, any JLS change that forcibly "reveals the truth" would be pretty disruptive (an example is the simple rule "allow capture anywhere"). See previous discussions in this thread for details. FYI I'll also ask my question on amber-spec-experts to get their opinion. Thanks, -Archie -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Wed Dec 11 22:24:12 2024 From: davidalayachew at gmail.com (David Alayachew) Date: Wed, 11 Dec 2024 17:24:12 -0500 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <83a9fa5b-69c1-47cd-bf2a-c49f16cda89f@oracle.com> <7c968acb-6db7-4a87-8b26-93f4f72050bf@oracle.com> <448f92ea-b103-4292-ae70-081ef71b3465@oracle.com> <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: Sure, but the same rules that allow the compiler to know that it is safe to use the variable for that instance of the for loop is more or less my point -- that should be extended outside of for loops too. I just take issue with adding this only for for loops or just loops. I understand that it would be heavy to apply this for more than just for-loops, but not doing so runs the risk of foreclosing potential solutions in the future when someone else like you comes asking for this for contexts outside of loops. On Wed, Dec 11, 2024 at 2:33?PM Archie Cobbs wrote: > Thanks for the comments. > > On Tue, Dec 10, 2024 at 8:44?PM David Alayachew > wrote: > >> The entire reason that this feature is being considered is because WE >> KNOW that we are being safe, but the compiler doesn't have enough info to >> know. >> > > I think it's more subtle than that... the compiler often does have enough > information, but there are some other reasons trying to extend this to all > "quiescent" variables would be tricky. > > One issue is that the JLS doesn't talk about variables being captured & > duplicated - even though we know that's what actually happens in practice. > In the JLS there's only one variable. Therefore, any JLS change that > forcibly "reveals the truth" would be pretty disruptive (an example is the > simple rule "allow capture anywhere"). See previous discussions in this > thread for details. > > FYI I'll also ask my question on amber-spec-experts to get their opinion. > > Thanks, > -Archie > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jean-noel.rouvignac at pingidentity.com Wed Dec 11 22:47:38 2024 From: jean-noel.rouvignac at pingidentity.com (=?UTF-8?Q?Jean=2DNo=C3=ABl_Rouvignac?=) Date: Wed, 11 Dec 2024 23:47:38 +0100 Subject: Enum: difference of behaviour between exhaustive switch vs. using default: In-Reply-To: References: <1251049146.19372898.1733921078225.JavaMail.zimbra@univ-eiffel.fr> Message-ID: Yes, I think you nailed it Liam. > I had thought that the difference might be related to the statement not > being an 'enhanced' switch statement (JLS 14.11.2), and how > non-enhanced switch statements are not required to be exhaustive. JLS 14.11.1.1 "Exhaustive Switch Blocks" section says switch statements can be exhaustive and IIUC this is the case here. > 14.11.3 says if no switch label applies, and the switch statement is not > enhanced, then it completes normally. So in the case of separate > compilation where a new constant is added to the enum after the switch > is compiled, the variable wouldn't be DA. > > Was that the intent here? Indeed, the automatically inserted `default:` clause only applies to switch expressions (as per JEP 361 "Switch Expressions" in the "Exhaustiveness" section). Switch statements, on the other side, are not _required_ to be or stay exhaustive, even in the face of separate compilation. Therefore, the error "variable s might not have been initialized" in the code example looks correct to me, although it can be troubling when one does not think about separate compilation. Good thinking. Thank you! On Wed, Dec 11, 2024 at 6:52?PM Liam Miller-Cushon wrote: > I had thought that the difference might be related to the statement not > being an 'enhanced' switch statement (JLS 14.11.2), and how non-enhanced > switch statements are not required to be exhaustive. > > 14.11.3 says if no switch label applies, and the switch statement is not > enhanced, then it completes normally. So in the case of separate > compilation where a new constant is added to the enum after the switch is > compiled, the variable wouldn't be DA. > > Was that the intent here? > > On Wed, Dec 11, 2024 at 9:43?AM Jean-No?l Rouvignac < > jean-noel.rouvignac at pingidentity.com> wrote: > >> Thank you all! >> >> I agree with Remi, the problem no longer exists when using a switch >> expression. >> I thought I could not do it with our (obviously more contrived) code, but >> I have managed to do it in the end. >> >> That said, after sending the email, I actually wondered if this problem >> was actually linked to the use of the "old switch" statement, and a >> possible lack of understanding of the control flow? >> I am ready to be told "we cannot fix it because of JLS rule 4.5.6.7" or >> something like that. >> >> Thank you again for taking a look at it, >> Jean-No?l >> >> >> >> >> On Wed, Dec 11, 2024 at 3:05?PM Angelos Bimpoudis < >> angelos.bimpoudis at oracle.com> wrote: >> >>> Filed it here: https://bugs.openjdk.org/browse/JDK-8345997 >>> >>> Thank you for reaching out! >>> Thx Remi for the minimized example as well. >>> ------------------------------ >>> *From:* amber-dev on behalf of Remi Forax < >>> forax at univ-mlv.fr> >>> *Sent:* 11 December 2024 13:44 >>> *To:* Gavin Bierman >>> *Cc:* Jean-No?l Rouvignac (ForgeRock) < >>> jean-noel.rouvignac at pingidentity.com>; amber-dev >>> *Subject:* Re: Enum: difference of behaviour between exhaustive switch >>> vs. using default: >>> >>> Hello, >>> I think it can be reduced to >>> >>> public enum Action { IGNORE, REJECT } >>> >>> private static void bad() { >>> String s; >>> switch (getAction()) { >>> case IGNORE: >>> s = "foo"; >>> break; >>> case REJECT: >>> throw new RuntimeException("REJECTED"); >>> }; >>> System.out.println(s); // <------- variable s might not have been initialized >>> } >>> >>> private static void ok() { >>> String s = switch (getAction()) { >>> case IGNORE: >>> yield "foo"; >>> case REJECT: >>> throw new RuntimeException("REJECTED"); >>> }; >>> System.out.println(s); // ok ! >>> } >>> >>> >>> so there is a bug in DA/DU rules and the workaround is to use a switch >>> expression. >>> >>> R?mi >>> >>> ------------------------------ >>> >>> *From: *"Gavin Bierman" >>> *To: *"Jean-No?l Rouvignac (ForgeRock)" < >>> jean-noel.rouvignac at pingidentity.com> >>> *Cc: *"amber-dev" >>> *Sent: *Wednesday, December 11, 2024 1:20:15 PM >>> *Subject: *Re: Enum: difference of behaviour between exhaustive switch >>> vs. using default: >>> >>> Could you file this as a bug, and I will take a look? >>> >>> Thanks, >>> Gavin >>> >>> On 10 Dec 2024, at 16:10, Jean-No?l Rouvignac (ForgeRock) < >>> jean-noel.rouvignac at pingidentity.com> wrote: >>> >>> Hello amber-dev experts! >>> >>> I am modernizing our codebase by making it use enhanced / exhaustive >>> switches. >>> >>> In several places, I replaced `default: ` by `case >>> THE_ONLY_UNUSED_ENUM_VALUE:`, except that I am hitting an unexpected >>> difference in behaviour, at least from my point of view. >>> >>> I have reduced the code to the following reproducer (tested on the >>> https://dev.java/playground/), where `main1()` compiles, but `main2()` >>> does not. And yet, I am under the impression both should be equivalent? >>> >>> What do you think? >>> Thanks a lot. >>> >>> >>> >>> import java.io.IOException; >>> >>> class Main { >>> public enum Action { IGNORE, REJECT } >>> >>> public static void main(String[] args) { >>> main1(); >>> main2(); >>> } >>> >>> private static void main1() { >>> String s; >>> try { >>> s = getValue(); >>> } catch (IOException e) { >>> switch (getAction()) { >>> case IGNORE: >>> return; >>> default: >>> throw new RuntimeException("REJECTED"); >>> } >>> } >>> >>> System.out.println(s); >>> } >>> >>> private static void main2() { >>> String s; >>> try { >>> s = getValue(); >>> } catch (IOException e) { >>> switch (getAction()) { >>> case IGNORE: >>> return; >>> case REJECT: // <------------------- Fails compilation >>> throw new RuntimeException("REJECTED"); >>> } >>> } >>> >>> System.out.println(s); // <------- Main.java:40: error: variable >>> s might not have been initialized >>> } >>> >>> static Action getAction() { >>> return Action.IGNORE; >>> } >>> >>> static String getValue() throws IOException { >>> return "SUCCESS"; >>> } >>> } >>> >>> >>> >>> *CONFIDENTIALITY NOTICE: This email may contain confidential and >>> privileged material for the sole use of the intended recipient(s). Any >>> review, use, distribution or disclosure by others is strictly prohibited. >>> If you have received this communication in error, please notify the sender >>> immediately by e-mail and delete the message and any file attachments from >>> your computer. Thank you.* >>> >>> >>> >>> >> >> -- >> [image: >> Ping Identity] >> Jean-Noel Rouvignac >> Senior Principal Software Engineer >> jean-noel.rouvignac at pingidentity.com >> >> >> >> >> Connect with us: >> [image: >> Glassdoor logo] >> >> [image: LinkedIn logo] >> >> [image: twitter logo] >> >> [image: facebook logo] >> >> [image: youtube logo] >> >> [image: Blog logo] >> >> To view our privacy policy, click here >> >> To stop receiving these emails, click here >> >> >> *CONFIDENTIALITY NOTICE: This email may contain confidential and >> privileged material for the sole use of the intended recipient(s). Any >> review, use, distribution or disclosure by others is strictly prohibited. >> If you have received this communication in error, please notify the sender >> immediately by e-mail and delete the message and any file attachments from >> your computer. Thank you.* > > -- [image: Ping Identity] Jean-Noel Rouvignac Senior Principal Software Engineer jean-noel.rouvignac at pingidentity.com Connect with us: [image: Glassdoor logo] [image: LinkedIn logo] [image: twitter logo] [image: facebook logo] [image: youtube logo] [image: Blog logo] To view our privacy policy, click here To stop receiving these emails, click here -- _CONFIDENTIALITY NOTICE: This email may contain confidential and privileged material for the sole use of the intended recipient(s). Any review, use, distribution or disclosure by others is strictly prohibited.? If you have received this communication in error, please notify the sender immediately by e-mail and delete the message and any file attachments from your computer. Thank you._ -------------- next part -------------- An HTML attachment was scrubbed... URL: From kevinb9n at gmail.com Wed Dec 11 23:00:22 2024 From: kevinb9n at gmail.com (Kevin Bourrillion) Date: Wed, 11 Dec 2024 15:00:22 -0800 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <83a9fa5b-69c1-47cd-bf2a-c49f16cda89f@oracle.com> <7c968acb-6db7-4a87-8b26-93f4f72050bf@oracle.com> <448f92ea-b103-4292-ae70-081ef71b3465@oracle.com> <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: Being under the impression that user-facing language-change decisions should be discussed in amber-spec-experts, I asked Archie to put a thread there as well. https://mail.openjdk.org/pipermail/amber-spec-experts/2024-December/004229.html That might have been cringe of me since this is already a 60-count thread as it is; if so... sorry! (reminder: non-EG members can subscribe to amber-spec-*observers* to follow that traffic.) I also gave my last-gasp consolidated argument *against* the change in reply, so we'll see. On Wed, Dec 11, 2024 at 2:24?PM David Alayachew wrote: > Sure, but the same rules that allow the compiler to know that it is safe > to use the variable for that instance of the for loop is more or less my > point -- that should be extended outside of for loops too. > > I just take issue with adding this only for for loops or just loops. I > understand that it would be heavy to apply this for more than just > for-loops, but not doing so runs the risk of foreclosing potential > solutions in the future when someone else like you comes asking for this > for contexts outside of loops. > > On Wed, Dec 11, 2024 at 2:33?PM Archie Cobbs > wrote: > >> Thanks for the comments. >> >> On Tue, Dec 10, 2024 at 8:44?PM David Alayachew >> wrote: >> >>> The entire reason that this feature is being considered is because WE >>> KNOW that we are being safe, but the compiler doesn't have enough info to >>> know. >>> >> >> I think it's more subtle than that... the compiler often does have enough >> information, but there are some other reasons trying to extend this to all >> "quiescent" variables would be tricky. >> >> One issue is that the JLS doesn't talk about variables being captured & >> duplicated - even though we know that's what actually happens in practice. >> In the JLS there's only one variable. Therefore, any JLS change that >> forcibly "reveals the truth" would be pretty disruptive (an example is the >> simple rule "allow capture anywhere"). See previous discussions in this >> thread for details. >> >> FYI I'll also ask my question on amber-spec-experts to get their opinion. >> >> Thanks, >> -Archie >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Thu Dec 12 01:17:14 2024 From: davidalayachew at gmail.com (David Alayachew) Date: Wed, 11 Dec 2024 20:17:14 -0500 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <83a9fa5b-69c1-47cd-bf2a-c49f16cda89f@oracle.com> <7c968acb-6db7-4a87-8b26-93f4f72050bf@oracle.com> <448f92ea-b103-4292-ae70-081ef71b3465@oracle.com> <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: Thanks for posting Kevin. To my understanding, the other mailing list is when they want an exclusive chat, whereas amber-dev is a free-for-all. But in regards to your post, it sounds like your 2 points boil down to the following. Allowing values from mutating variables to be captured in a lambda will open the serious can of worms about where and when a mutable variable's value is safe to capture. We currently have a very simple (albeit, restricting) set of rules that leave out much of the ambiguity by just universally saying "NO" unless it is effectively final. Would that be a correct summary of your post? If so, then I firmly agree with you. I'd even go further -- if we do decide to open up the can of worms, we can't just kill one of them -- we need to kill them all. We need to fully specify when and where it is safe for a mutable variables value to be used. No special-casing for for-loops -- the logic would need to be something that can be UTILIZED by for-loops, but shouldn't belong to them at all. And while I would prefer to kill all the worms (again, even beginner's lament that they KNOW they are safe to use the value), I am also ok with just doing nothing and sticking with the status quo. On Wed, Dec 11, 2024 at 6:00?PM Kevin Bourrillion wrote: > Being under the impression that user-facing language-change decisions > should be discussed in amber-spec-experts, I asked Archie to put a thread > there as well. > > https://mail.openjdk.org/pipermail/amber-spec-experts/2024-December/004229.html > > That might have been cringe of me since this is already a 60-count thread > as it is; if so... sorry! > > (reminder: non-EG members can subscribe to amber-spec-*observers* to > follow that traffic.) > > I also gave my last-gasp consolidated argument *against* the change in > reply, so we'll see. > > > On Wed, Dec 11, 2024 at 2:24?PM David Alayachew > wrote: > >> Sure, but the same rules that allow the compiler to know that it is safe >> to use the variable for that instance of the for loop is more or less my >> point -- that should be extended outside of for loops too. >> >> I just take issue with adding this only for for loops or just loops. I >> understand that it would be heavy to apply this for more than just >> for-loops, but not doing so runs the risk of foreclosing potential >> solutions in the future when someone else like you comes asking for this >> for contexts outside of loops. >> >> On Wed, Dec 11, 2024 at 2:33?PM Archie Cobbs >> wrote: >> >>> Thanks for the comments. >>> >>> On Tue, Dec 10, 2024 at 8:44?PM David Alayachew < >>> davidalayachew at gmail.com> wrote: >>> >>>> The entire reason that this feature is being considered is because WE >>>> KNOW that we are being safe, but the compiler doesn't have enough info to >>>> know. >>>> >>> >>> I think it's more subtle than that... the compiler often does have >>> enough information, but there are some other reasons trying to extend this >>> to all "quiescent" variables would be tricky. >>> >>> One issue is that the JLS doesn't talk about variables being captured & >>> duplicated - even though we know that's what actually happens in practice. >>> In the JLS there's only one variable. Therefore, any JLS change that >>> forcibly "reveals the truth" would be pretty disruptive (an example is the >>> simple rule "allow capture anywhere"). See previous discussions in this >>> thread for details. >>> >>> FYI I'll also ask my question on amber-spec-experts to get their opinion. >>> >>> Thanks, >>> -Archie >>> >>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From magnus.ihse.bursie at oracle.com Thu Dec 12 10:18:59 2024 From: magnus.ihse.bursie at oracle.com (Magnus Ihse Bursie) Date: Thu, 12 Dec 2024 11:18:59 +0100 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" Message-ID: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> I've been lurking in this list for quite some while. It's very interesting too see all creative proposal, and always very refreshing to read the well-formulated replies (often by Brian, but many others contribute as well) on why this-or-that is not feasible. I think the list archive contains a treasure trove of information about possible language features and ways Java development could have gone, but did not -- and with good explanations of why that was not as good idea as it looked in the first place. However, this treasure is hard to find. If you follow the list, you see it pop up from time to time, but if you don't, there is no easy way to get to this. This tend to lead to some popular ideas being suggested over and over again (perhaps not as much here, as on other channels, like Reddit). I think it would be great if these suggestion, together with the reasoning provided for not implementing it, were collected on a web site. The wiki seems to be a good place, but there are of course many other possible solutions. I have contemplated doing this myself for quite some time, going through the mail archive and extracting the relevant discussions, but I always have more pressing things to do, and it is not likely I will ever be able to do it. So I'm throwing this idea up in the air. I realize many other are in the same situation as I am, but perhaps there are some interested readers?out there in the community that has more time on their hands and that can help with such a task? /Magnus From dvohra16 at gmail.com Thu Dec 12 14:35:04 2024 From: dvohra16 at gmail.com (Deepak Vohra) Date: Thu, 12 Dec 2024 06:35:04 -0800 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" In-Reply-To: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> References: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> Message-ID: Hi Magnus, I like Java for its imperfections. However, some improvements could help steer it toward the #1 spot it once held. Please initiate some detail how I may help, such as peruse the list for potential items to include in such a list. Deepak On Thu, Dec 12, 2024 at 3:28?AM Magnus Ihse Bursie < magnus.ihse.bursie at oracle.com> wrote: > I've been lurking in this list for quite some while. It's very > interesting too see all creative proposal, and always very refreshing to > read the well-formulated replies (often by Brian, but many others > contribute as well) on why this-or-that is not feasible. > > I think the list archive contains a treasure trove of information about > possible language features and ways Java development could have gone, > but did not -- and with good explanations of why that was not as good > idea as it looked in the first place. > > However, this treasure is hard to find. If you follow the list, you see > it pop up from time to time, but if you don't, there is no easy way to > get to this. This tend to lead to some popular ideas being suggested > over and over again (perhaps not as much here, as on other channels, > like Reddit). > > I think it would be great if these suggestion, together with the > reasoning provided for not implementing it, were collected on a web > site. The wiki seems to be a good place, but there are of course many > other possible solutions. > > I have contemplated doing this myself for quite some time, going through > the mail archive and extracting the relevant discussions, but I always > have more pressing things to do, and it is not likely I will ever be > able to do it. So I'm throwing this idea up in the air. I realize many > other are in the same situation as I am, but perhaps there are some > interested readers out there in the community that has more time on > their hands and that can help with such a task? > > /Magnus > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu Dec 12 16:06:25 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 12 Dec 2024 11:06:25 -0500 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" In-Reply-To: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> References: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> Message-ID: During the Java 8 days many of these found their way to Stack Overflow, and several of us (myself and Stuart especially) invested in creating good answers to these, to the point where eventually several folks in the community were able to start answering these rationale questions.? There were a few folks who were pretty adept at ferreting out details from the lists and posting pointers.? This worked really well, and the effort of this dwindled over time.? But then AI ate (or threatened to eat) Stack Overflow, and it became a less effective filter for these questions. I don't love being in the position of having to say "yes, we've talked about this plenty", since it's unreasonable to expect everyone to have read the entire history of all the various places where these things are discussed.? So I would be happy to see some folks index some of the past discussions, as it increases the value of answering these questions (because more people are likely to see it.)? But it's definitely work. There's an OpenJDK wiki but which is mostly abandoned.? There is the amber-docs repo which gets published to `openjdk.org/projects/amber`, which is probably a better place to put it, and people can contribute via PRs. On 12/12/2024 5:18 AM, Magnus Ihse Bursie wrote: > I've been lurking in this list for quite some while. It's very > interesting too see all creative proposal, and always very refreshing > to read the well-formulated replies (often by Brian, but many others > contribute as well) on why this-or-that is not feasible. > > I think the list archive contains a treasure trove of information > about possible language features and ways Java development could have > gone, but did not -- and with good explanations of why that was not as > good idea as it looked in the first place. > > However, this treasure is hard to find. If you follow the list, you > see it pop up from time to time, but if you don't, there is no easy > way to get to this. This tend to lead to some popular ideas being > suggested over and over again (perhaps not as much here, as on other > channels, like Reddit). > > I think it would be great if these suggestion, together with the > reasoning provided for not implementing it, were collected on a web > site. The wiki seems to be a good place, but there are of course many > other possible solutions. > > I have contemplated doing this myself for quite some time, going > through the mail archive and extracting the relevant discussions, but > I always have more pressing things to do, and it is not likely I will > ever be able to do it. So I'm throwing this idea up in the air. I > realize many other are in the same situation as I am, but perhaps > there are some interested readers?out there in the community that has > more time on their hands and that can help with such a task? > > /Magnus > -------------- next part -------------- An HTML attachment was scrubbed... URL: From eirbjo at gmail.com Thu Dec 12 18:31:27 2024 From: eirbjo at gmail.com (=?UTF-8?B?RWlyaWsgQmrDuHJzbsO4cw==?=) Date: Thu, 12 Dec 2024 19:31:27 +0100 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" In-Reply-To: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> References: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> Message-ID: On Thu, Dec 12, 2024 at 12:28?PM Magnus Ihse Bursie < magnus.ihse.bursie at oracle.com> wrote: > I've been lurking in this list for quite some while. It's very > interesting too see all creative proposal, and always very refreshing to > read the well-formulated replies (often by Brian, but many others > contribute as well) on why this-or-that is not feasible. > This made think back to Project Jigsaw and its Issue Summary document: https://openjdk.org/projects/jigsaw/spec/issues/ That document (particularly the way it assigned unique #HashTags) made it easy for the community to follow the various questions/ideas/features raised during the course of the project. Maybe that document could be inspirational if somebody takes on the task to make something similar for Amber-related issues / questions / ideas. Thanks, Eirik. -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Thu Dec 12 18:34:22 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Thu, 12 Dec 2024 12:34:22 -0600 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" In-Reply-To: References: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> Message-ID: On Thu, Dec 12, 2024 at 10:07?AM Brian Goetz wrote: > There is the amber-docs repo which gets published to ` > openjdk.org/projects/amber` , which is > probably a better place to put it, and people can contribute via PRs. > I think putting something online under amber-docs is a great idea - especially the part where people can contribute using PR's, which fosters decentralized collaboration on the maintenance of the list. While it would be ideal to have a complete directory of ideas with accompanying summaries of all that has been discussed, we should probably start with something simpler and more maintainable. Here's a proposal: Have a list of "previously discussed ideas". Each idea has a one line description, a one paragraph summary, an optional example, and a bullet-point list of one or more links to the thread(s) in the archive that contain all the gory details of the discussion. Here's a simple example... *Idea:* Using switch statements for if/else control flow *Description:* Support "switches on nothing" where the cases simply provide the conditions on which to execute various code branches. *Example:* public double toInches(String value) { switch { case when value.endsWith("mm") -> return 0.0393701 * Integer.parseInt(value.substring(0, value.length() - 2)); case when value.endsWith("ft") -> return 12 * Integer.parseInt(value.substring(0, value.length() - 2)); case when value.endsWith("light-years") -> return 3.725e+17 * Integer.parseInt(value.substring(0, value.length() - 2)); default -> throw new IllegalArgumentException("can't parse value"); } } *Discussion:* - https://mail.openjdk.org/pipermail/amber-dev/2024-October/008939.html Just now seeing Eirik's reference to Project Jigsaw's Issue Summary document. I like this even better but someone would have to step up and take ownership. -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From lowasser at google.com Thu Dec 12 19:41:50 2024 From: lowasser at google.com (Louis Wasserman) Date: Thu, 12 Dec 2024 11:41:50 -0800 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" In-Reply-To: References: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> Message-ID: Just seeing that it hasn't been mentioned, Guava's Idea Graveyard is an example of this specific flavor of thing: https://github.com/google/guava/wiki/IdeaGraveyard. (It's pretty old, though, which reflects some of the downsides.) On Thu, Dec 12, 2024 at 10:34?AM Archie Cobbs wrote: > On Thu, Dec 12, 2024 at 10:07?AM Brian Goetz > wrote: > >> There is the amber-docs repo which gets published to ` >> openjdk.org/projects/amber` , which >> is probably a better place to put it, and people can contribute via PRs. >> > > I think putting something online under amber-docs is a great idea - > especially the part where people can contribute using PR's, which fosters > decentralized collaboration on the maintenance of the list. > > While it would be ideal to have a complete directory of ideas with > accompanying summaries of all that has been discussed, we should probably > start with something simpler and more maintainable. > > Here's a proposal: Have a list of "previously discussed ideas". Each idea > has a one line description, a one paragraph summary, an optional example, > and a bullet-point list of one or more links to the thread(s) in the > archive that contain all the gory details of the discussion. > > Here's a simple example... > > *Idea:* Using switch statements for if/else control flow > > *Description:* Support "switches on nothing" where the cases simply > provide the conditions on which to execute various code branches. > > *Example:* > > public double toInches(String value) { > switch { > case when value.endsWith("mm") -> return 0.0393701 * > Integer.parseInt(value.substring(0, value.length() - 2)); > case when value.endsWith("ft") -> return 12 * > Integer.parseInt(value.substring(0, value.length() - 2)); > case when value.endsWith("light-years") -> return 3.725e+17 * > Integer.parseInt(value.substring(0, value.length() - 2)); > default -> throw new IllegalArgumentException("can't parse value"); > } > } > > *Discussion:* > > - https://mail.openjdk.org/pipermail/amber-dev/2024-October/008939.html > > > Just now seeing Eirik's reference to Project Jigsaw's Issue Summary > document. I like this even better but someone would have to step up and > take ownership. > > -Archie > > -- > Archie L. Cobbs > -- Louis Wasserman (he/they) -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu Dec 12 19:53:10 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 12 Dec 2024 14:53:10 -0500 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" In-Reply-To: References: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> Message-ID: <8ae9ecd6-a905-4877-a032-a982c21b4009@oracle.com> One thing to be clear on about this effort is: this is not about lobbying for the priority of "my favorite feature"; this is merely about capturing explanations that have been previously shared, so others can find them more easily. One aspect of moral hazard here is that it is a natural tendency to browse this archive and then barge into the list with "But I don't agree with your arguments on feature #7."? But the goal here is to reduce redundant "why don't you" requests, not increase it. Framing the purpose of this artifact clearly can help manage this. On 12/12/2024 1:34 PM, Archie Cobbs wrote: > On Thu, Dec 12, 2024 at 10:07?AM Brian Goetz > wrote: > > There is the amber-docs repo which gets published to > `openjdk.org/projects/amber` , > which is probably a better place to put it, and people can > contribute via PRs. > > > I think putting something online under amber-docs is a great idea - > especially the part where people can contribute using PR's, which > fosters decentralized collaboration on the maintenance of the list. > > While it would be ideal to have a complete directory of ideas with > accompanying summaries of all that has been discussed, we should > probably start with something simpler and more maintainable. > > Here's a proposal: Have a list of "previously discussed ideas". Each > idea has a one line description, a one paragraph summary, an optional > example, and a bullet-point list of one or more links to the thread(s) > in the archive that contain all the gory details of the discussion. > > Here's a simple example... > > *Idea:* Using switch statements for if/else control flow > > *Description:* Support "switches on nothing" where the cases simply > provide the conditions on which to execute various code branches. > > *Example:* > > ??? public double toInches(String value) { > ??????? switch { > ??????? case when value.endsWith("mm") -> return 0.0393701 * > Integer.parseInt(value.substring(0, value.length() - 2)); > ??????? case when value.endsWith("ft") -> return 12 * > Integer.parseInt(value.substring(0, value.length() - 2)); > ??????? case when value.endsWith("light-years") ->?return 3.725e+17 * > Integer.parseInt(value.substring(0, value.length() - 2)); > ??????? default -> throw new IllegalArgumentException("can't parse > value"); > ??????? } > ??? } > > *Discussion:* > > * https://mail.openjdk.org/pipermail/amber-dev/2024-October/008939.html > > > Just now seeing Eirik's reference to Project Jigsaw's Issue Summary > document. I like this even better but someone would have to step up > and take ownership. > > -Archie > > -- > Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From ethan at mccue.dev Fri Dec 13 03:02:56 2024 From: ethan at mccue.dev (Ethan McCue) Date: Fri, 13 Dec 2024 12:02:56 +0900 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" In-Reply-To: References: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> Message-ID: One practical trouble in assembling this is that the mailing lists aren't exactly indexed/searchable. Another orthogonal concern is that we are currently at a point in history where most people involved in important choices over time are still alive. Starting to do historian work is important for reasons other than dealing with "why don't you"s. I'll make it my project to put something together by new years though. On Fri, Dec 13, 2024, 6:26 AM Louis Wasserman wrote: > Just seeing that it hasn't been mentioned, Guava's Idea Graveyard is an > example of this specific flavor of thing: > https://github.com/google/guava/wiki/IdeaGraveyard. (It's pretty old, > though, which reflects some of the downsides.) > > On Thu, Dec 12, 2024 at 10:34?AM Archie Cobbs > wrote: > >> On Thu, Dec 12, 2024 at 10:07?AM Brian Goetz >> wrote: >> >>> There is the amber-docs repo which gets published to ` >>> openjdk.org/projects/amber` , which >>> is probably a better place to put it, and people can contribute via PRs. >>> >> >> I think putting something online under amber-docs is a great idea - >> especially the part where people can contribute using PR's, which fosters >> decentralized collaboration on the maintenance of the list. >> >> While it would be ideal to have a complete directory of ideas with >> accompanying summaries of all that has been discussed, we should probably >> start with something simpler and more maintainable. >> >> Here's a proposal: Have a list of "previously discussed ideas". Each idea >> has a one line description, a one paragraph summary, an optional example, >> and a bullet-point list of one or more links to the thread(s) in the >> archive that contain all the gory details of the discussion. >> >> Here's a simple example... >> >> *Idea:* Using switch statements for if/else control flow >> >> *Description:* Support "switches on nothing" where the cases simply >> provide the conditions on which to execute various code branches. >> >> *Example:* >> >> public double toInches(String value) { >> switch { >> case when value.endsWith("mm") -> return 0.0393701 * >> Integer.parseInt(value.substring(0, value.length() - 2)); >> case when value.endsWith("ft") -> return 12 * >> Integer.parseInt(value.substring(0, value.length() - 2)); >> case when value.endsWith("light-years") -> return 3.725e+17 * >> Integer.parseInt(value.substring(0, value.length() - 2)); >> default -> throw new IllegalArgumentException("can't parse >> value"); >> } >> } >> >> *Discussion:* >> >> - >> https://mail.openjdk.org/pipermail/amber-dev/2024-October/008939.html >> >> >> Just now seeing Eirik's reference to Project Jigsaw's Issue Summary >> document. I like this even better but someone would have to step up and >> take ownership. >> >> -Archie >> >> -- >> Archie L. Cobbs >> > > > -- > Louis Wasserman (he/they) > -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Sat Dec 14 13:51:55 2024 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 14 Dec 2024 14:51:55 +0100 (CET) Subject: anonymous records as an implementation for tuples in Java In-Reply-To: <6f0d9ba5-f4c2-441d-a4b0-1f7fa1b456c9@oracle.com> References: <6f0d9ba5-f4c2-441d-a4b0-1f7fa1b456c9@oracle.com> Message-ID: <1710302465.23315019.1734184315071.JavaMail.zimbra@univ-eiffel.fr> > From: "Brian Goetz" > To: "Red IO" > Cc: "david Grajales" , "amber-dev" > > Sent: Wednesday, December 11, 2024 6:27:13 PM > Subject: Re: anonymous records as an implementation for tuples in Java > 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.) Is it not the same issue as when you have a deconstructor method in one class and a switch on it in another class ? class Foo { deconstructor (String s, int i) Foo { ... } ... } Foo foo = ... switch(foo) { case Foo(String s, int i) -> ... } R?mi > 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 < [ mailto:brian.goetz at oracle.com | >> 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 = [ >>>> https://urldefense.com/v3/__http://tuple.id__;!!ACWV5N9M2RV99hQ!JWvS3-XRXfU_BDrdY-5L5h1ddl_PStJP3vNDQtkLvrxFIdBwPvzjEW-LMmG4r8MykbGgC-Y4e8oBmPElPpwijXdqZiO2$ >>>> | tuple.id ] () >>>> for passing them as arguments to methods it could be something like this. >>>> void foo(Tuple 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. -------------- next part -------------- An HTML attachment was scrubbed... URL: From johannes.spangenberg at hotmail.de Sun Dec 15 11:26:36 2024 From: johannes.spangenberg at hotmail.de (Johannes Spangenberg) Date: Sun, 15 Dec 2024 12:26:36 +0100 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: Just wanted to mention that I have also seen the pattern of creating a proxy and calling the lambda on the proxy to detect the method for a method reference. However, this works only with methods on interfaces. From david.1993grajales at gmail.com Sun Dec 15 15:16:59 2024 From: david.1993grajales at gmail.com (david Grajales) Date: Sun, 15 Dec 2024 10:16:59 -0500 Subject: anonymous records as an implementation for tuples in Java In-Reply-To: <1710302465.23315019.1734184315071.JavaMail.zimbra@univ-eiffel.fr> References: <6f0d9ba5-f4c2-441d-a4b0-1f7fa1b456c9@oracle.com> <1710302465.23315019.1734184315071.JavaMail.zimbra@univ-eiffel.fr> Message-ID: I have been reading the JEP: Frozen Arrays https://openjdk.org/jeps/8261007 Wouldn't this be equivalent to python tuples in practice? If so why don't just call it tuples so it's more familiar with what most people already know for s tuple? Or does it have some difference that scapes me or does the amber team has a more richful feature in mind to be called "tuple" in an hypothetical future? Best regards! El s?b, 14 de dic de 2024, 8:51?a. m., Remi Forax escribi?: > > > ------------------------------ > > *From: *"Brian Goetz" > *To: *"Red IO" > *Cc: *"david Grajales" , "amber-dev" < > amber-dev at openjdk.org> > *Sent: *Wednesday, December 11, 2024 6:27:13 PM > *Subject: *Re: anonymous records as an implementation for tuples in Java > > 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.) > > > Is it not the same issue as when you have a deconstructor method in one > class and a switch on it in another class ? > > class Foo { > deconstructor (String s, int i) Foo { ... } > ... > } > > Foo foo = ... > switch(foo) { > case Foo(String s, int i) -> ... > } > > R?mi > > > > 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 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 >> >> () >> >> for passing them as arguments to methods it could be something like this. >> >> void foo(Tuple 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 automaticequals(),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. >> >> >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Sun Dec 15 15:22:51 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 15 Dec 2024 10:22:51 -0500 Subject: anonymous records as an implementation for tuples in Java In-Reply-To: References: <6f0d9ba5-f4c2-441d-a4b0-1f7fa1b456c9@oracle.com> <1710302465.23315019.1734184315071.JavaMail.zimbra@univ-eiffel.fr> Message-ID: <36280d48-7a01-4e1a-acd8-5382af7e7145@oracle.com> No, frozen arrays has nothing to do with tuples.? It has to do with making arrays safe to share without need for copying and without fear of unexpected mutation. (An array can have only a single component type, and the size is only known to the dynamic type system, so while in theory an array could be the backing store for any tuple, these tuples would be very weakly typed -- you would have no ability to differentiate "tuple of string and int" from "tuple of seven floats".) On 12/15/2024 10:16 AM, david Grajales wrote: > > I have been reading the JEP: Frozen Arrays > https://openjdk.org/jeps/8261007 > > Wouldn't this be equivalent to python tuples in practice? If so why > don't just call it tuples so it's more familiar with what most people > already know for s tuple? > > Or does it have some difference that scapes me or does the amber team > has a more richful feature in mind to be called "tuple" in an > hypothetical future? > > Best regards! > > > El s?b, 14 de dic de 2024, 8:51?a.?m., Remi Forax > escribi?: > > > > ------------------------------------------------------------------------ > > *From: *"Brian Goetz" > *To: *"Red IO" > *Cc: *"david Grajales" , > "amber-dev" > *Sent: *Wednesday, December 11, 2024 6:27:13 PM > *Subject: *Re: anonymous records as an implementation for > tuples in Java > > 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.) > > > Is it not the same issue as when you have a deconstructor method > in one class and a switch on it in another class ? > > ? class Foo { > ??? deconstructor (String s, int i) Foo { ... } > ??? ... > ? } > > ? Foo foo = ... > ? switch(foo) { > ??? case Foo(String s, int i) -> ... > ? } > > R?mi > > > > 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 > 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 > () > > for passing them as arguments to methods it could > be something like this. > > void foo(Tuple 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. > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Sun Dec 15 18:49:25 2024 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Sun, 15 Dec 2024 19:49:25 +0100 (CET) Subject: amber-dev Digest, Vol 94, Issue 15 In-Reply-To: References: Message-ID: <1292303321.24628938.1734288565513.JavaMail.zimbra@univ-eiffel.fr> Mine are covariant, try to not box and works across API boundaries :) (and also are typed as Object so they require compiler support, which is ... missing) https://github.com/forax/tuple-factory/ R?mi PS: they should work well with Valhalla. > From: "Vikram Bakshi" > To: "amber-dev" , "Remi Forax" > Sent: Tuesday, December 10, 2024 11:52:42 PM > Subject: Re: amber-dev Digest, Vol 94, Issue 15 > Might be off-topic for the mailing list but I thought I would share since it is > on topic for the thread. > Remi - you might like my library: [ https://easytuples.github.io/easy-tuples/ | > https://easytuples.github.io/easy-tuples/ ] > It is intended to provide as close to "structural" tuples as I think are > possible in Java right now. > On a previous thread it was stated that the in-place destructuring will come > (nominal de-structuring of course not structural) but is lower priority. > See: [ https://mail.openjdk.org/pipermail/amber-dev/2024-December/009105.html | > https://mail.openjdk.org/pipermail/amber-dev/2024-December/009105.html ] > Your example: > (int min, int max) minmax(int a, int b) { > return (Math.min(a, b), Math.max(a, b)); > } > void main() { > var (min, max) = minmax(7, 3); > // or > var result = minmax(...(7, 3)); // with a spread operator > } > Could eventually become: > _2 minmax(int a, int b) { > return _2.of(Math.min(a,b), Math.max(a,b)); > } > void main() { > _2(var min, var max) pair = minmax(7,3); > } > (the _2 type is my 'structural' pair tuple in the library I mentioned above) > Regards, > Vikram > On Tue, Dec 10, 2024 at 10:01 AM < [ mailto:amber-dev-request at openjdk.org | > amber-dev-request at openjdk.org ] > wrote: >> 2. Re: Constructing records through reflection and module >> restrictions ( [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] ) >> Message: 2 >> Date: Tue, 10 Dec 2024 11:00:57 +0100 (CET) >> From: [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] >> To: Ryan Leach < [ mailto:rleach at rleach.id.au | rleach at rleach.id.au ] >, Ethan >> McCue < [ mailto:ethan at mccue.dev | ethan at mccue.dev ] > >> Cc: amber-dev < [ mailto:amber-dev at openjdk.org | amber-dev at openjdk.org ] > >> Subject: Re: Constructing records through reflection and module >> restrictions >> Message-ID: >> < [ mailto:1055813512.18413861.1733824857389.JavaMail.zimbra at univ-eiffel.fr | >> 1055813512.18413861.1733824857389.JavaMail.zimbra at univ-eiffel.fr ] > >> Content-Type: text/plain; charset="utf-8" >> > From: "Ethan McCue" < [ mailto:ethan at mccue.dev | ethan at mccue.dev ] > >> > I'd wager the feature being missed in those cases is in-place destructing, less >> > so anonymous components. >> > From: "Ryan Leach" < [ mailto:rleach at rleach.id.au | rleach at rleach.id.au ] > >> > The way I've seen records adopted and used, seem pretty far removed from Tuples, >> > so don't really understand why you are in support of making them more >> > Tuple-like Remi. I suspect we'll see true Tuples being introduced long before >> > records are considered to be turned into Tuples. Not that I suspect that's >> > particularly likely. >> yes, i'm not arguying that records should be tuples, only that for a lot of my >> students, they see tuples are a building block and Java is missing that. >> As Ethan said, in-place structuring/destructing is another name for tuples (with >> named components). >> By examples: >> (int min, int max) minmax(int a, int b) { >> return (Math.min(a, b), Math.max(a, b)); >> } >> void main() { >> var (min, max) = minmax(7, 3); >> // or >> var result = minmax(...(7, 3)); // with a spread operator >> } >> As Brian said, the main issue here is that those things are structural typed, >> not nominally typed. >> R?mi >>> On Mon, 9 Dec 2024, 3:07 am Remi Forax, < [ mailto: [ mailto:forax at univ-mlv.fr | >> > forax at univ-mlv.fr ] | >> > [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] ] > wrote: >>>>> From: "Brian Goetz" < [ mailto: [ mailto:brian.goetz at oracle.com | >>>>> brian.goetz at oracle.com ] | [ mailto:brian.goetz at oracle.com | >> >>> brian.goetz at oracle.com ] ] >>>>> To: "Florian Weimer" < [ mailto: [ mailto:fw at deneb.enyo.de | fw at deneb.enyo.de ] >> >>> | [ mailto:fw at deneb.enyo.de | fw at deneb.enyo.de ] ] > >>>>> Cc: "amber-dev" < [ mailto: [ mailto:amber-dev at openjdk.org | >>>>> amber-dev at openjdk.org ] | [ mailto:amber-dev at openjdk.org | >> >>> amber-dev at openjdk.org ] ] > >> >>> Sent: Sunday, December 8, 2024 4:50:43 PM >> >>> Subject: Re: Constructing records through reflection and module restrictions >> >>> Sure, there are other ways we could have designed the language. Tuples are >> >>> structural types, which means they are not declared, but instead spring when >> >>> the type constructor is applied to other (necessarily accessible) types. This >> >>> means there is no need for access control, since anyone who can access T and U >> >>> can "summon" the type `tuple`. (We have this for arrays already -- which >> >>> is already a significant source of irregularity in the language, so we chose >> >>> not to emulate that.) >> >>> But, we chose to lean into Java's class-based, nominal type system. Making >> >>> special exceptions "because it's like a tuple" is surely convenience in some >> >>> cases, but makes the language more complicated to reason about overall. >> >> We have made an exception for lambdas. >> >> There is something special with tuples, most of my students now learn >> >> programming with Python as first langage, so there are used to use tuples as an >> >> element of design. >> >> As an example, when students start Java, we have a course to explain that Java >> >> has no tuples and the difference between a record and a tuple. >> >> Another example, currently, this is the time of the year where we are doing the >> >> advent of code, students can choose the langage they want, most of the >> >> undergraduate students choose Python. >> >> When asked why, having tuples is the most cited feature, and it makes sense >> >> given the kind of problems of the advent of code. >> >> I think we will have to fix this in Java at some point, not now, perhaps even >> >> not us, but exactly like we did not need lambdas because we had inner classes, >> >> not having tuples will be seen increasingly as a Java problem. >> >> regards, >> >> R?mi >> >> NB: For graduate students, most of them are using Java for the advent of code, >> >> but i suppose this is a kind of Stockholm syndrome reaction because they are >> >> using Java in most of their courses (concurrency, android, http server, design >> >> pattern, spring, etc). >> >>> On 12/8/2024 10:15 AM, Florian Weimer wrote: >> >>>> It's the syntactic overhead. The attractiveness of this pattern is >> >>>> that's it's a clear and concise notation for this type of >> >>>> deserialization. Creating a public type for it in a suitable package >> >>>> sort of breaks that. >> -------------- next part -------------- >> An HTML attachment was scrubbed... >> URL: < [ >> https://mail.openjdk.org/pipermail/amber-dev/attachments/20241210/bf0ddbb3/attachment.htm >> | >> https://mail.openjdk.org/pipermail/amber-dev/attachments/20241210/bf0ddbb3/attachment.htm >> ] > >> End of amber-dev Digest, Vol 94, Issue 15 >> ***************************************** -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Mon Dec 16 11:10:08 2024 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 16 Dec 2024 11:10:08 +0000 Subject: Improving Method Reference Ergonomics In-Reply-To: References: Message-ID: <40de64c4-ad8b-4d78-9cbc-fbe1f2ef037d@oracle.com> Hi, Project Babylon might provide a slightly different path to get where you want to go. Look at the examples discussed in this great article by Paul: https://openjdk.org/projects/babylon/articles/linq With code reflection, the compiler reifies the entire expression `Customer::new` (including all the symbolic references) into an instance of a code model (`Op`) which can then be dissected/inspected/transformed at runtime as you see fit. I agree that, as others have said, just doing point-improvements on how _all_ method references are represented by the runtime isn't going to cut it -- what you want is the source model available, more or less unchanged, at runtime -- which is the goal of Project Babylon's code reflection. Cheers Maurizio On 09/12/2024 01:52, Peter Eastham wrote: > Hi Amber team, > > Earlier this week I was playing around with fluent API design, and I > believe Java could benefit from some improvements to the usage of > Method References, I'll keep this short with the following example. > > Lets take the following JPA Criteria from section 6.3.3 of the > Specification, (Only for an example of what an API could begin doing, > not should do) > CriteriaQuery q = cb.createQuery(Customer.class); > Root customer = q.from(Customer.class); > Join order = customer.join(Customer_.orders, JoinType.LEFT); > q.where(cb.equal(customer.get(Customer_.status), 1)).select(customer); > > If there was greater access to the Method Reference more implicit > information could be passed, reducing the noise, > CriteriaQuery q = CriteriaQuery.createQuery(Customer::new) > ? .leftJoin(Customer::orders) > ? .where(Object::equals, Customer::status, 1); > var result = q.select(); > > Regarding what should be available, the resolved Class and Method name > at least, anything else I'd leave up to the feasibility of the change. > > Thanks, > -Peter From brian.goetz at oracle.com Tue Dec 17 19:23:11 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 17 Dec 2024 14:23:11 -0500 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: > To my understanding, the other mailing list is when they want an > exclusive chat, whereas amber-dev is a free-for-all. I'd like to correct this perception, because amber-dev is definitely not intended to be any sort of free-for-all. The charter of amber-dev is discussion pertaining to the _implementation_ of Amber features.? This includes implementation discussions, bug reports, "is this how it is supposed to work" questions, experience reports ("I tried it and ___").? It is definitely and explicitly *not* a place for language design discussion, nor a place for "I have an idea for amber". That said, in the interest of inclusion and helpfulness, we are often tolerant of certain _limited_ discussions outside the charter.? We try to allow discussions to continue until they have clearly wandered out of bounds, but we also hope that people exercise restraint so that we can continue to do so. -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Wed Dec 18 00:18:00 2024 From: davidalayachew at gmail.com (David Alayachew) Date: Tue, 17 Dec 2024 19:18:00 -0500 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: Thanks for clarifying Brian. On Tue, Dec 17, 2024 at 2:23?PM Brian Goetz wrote: > > > To my understanding, the other mailing list is when they want an exclusive > chat, whereas amber-dev is a free-for-all. > > > I'd like to correct this perception, because amber-dev is definitely not > intended to be any sort of free-for-all. > > The charter of amber-dev is discussion pertaining to the _implementation_ > of Amber features. This includes implementation discussions, bug reports, > "is this how it is supposed to work" questions, experience reports ("I > tried it and ___"). It is definitely and explicitly *not* a place for > language design discussion, nor a place for "I have an idea for amber". > > That said, in the interest of inclusion and helpfulness, we are often > tolerant of certain _limited_ discussions outside the charter. We try to > allow discussions to continue until they have clearly wandered out of > bounds, but we also hope that people exercise restraint so that we can > continue to do so. > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Thu Dec 19 15:39:10 2024 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Thu, 19 Dec 2024 09:39:10 -0600 Subject: JDK-8300691 - final variables in for loop headers should accept updates In-Reply-To: References: <83a9fa5b-69c1-47cd-bf2a-c49f16cda89f@oracle.com> <7c968acb-6db7-4a87-8b26-93f4f72050bf@oracle.com> <448f92ea-b103-4292-ae70-081ef71b3465@oracle.com> <507dbbe7-94d3-4dd6-8a13-afecbe599271@oracle.com> <094AF589-9E12-4F46-B512-BEEC3135380A@oracle.com> <9488f6b8-95a8-4d4a-bf54-757297eaff96@oracle.com> <3ACF4EBB-F749-4887-B005-7EA20A355099@oracle.com> Message-ID: On Wed, Dec 11, 2024 at 5:00?PM Kevin Bourrillion wrote: > Being under the impression that user-facing language-change decisions > should be discussed in amber-spec-experts, I asked Archie to put a thread > there as well. > > https://mail.openjdk.org/pipermail/amber-spec-experts/2024-December/004229.html > We didn't get a strong enough positive response on amber-spec-experts (actually, we got no response :) so I'll shelve this idea for now. Thanks for all the discussion - it has revealed (yet again) how there is a lot of subtlety to even very minor language changes! -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From magnus.ihse.bursie at oracle.com Fri Dec 20 14:26:12 2024 From: magnus.ihse.bursie at oracle.com (Magnus Ihse Bursie) Date: Fri, 20 Dec 2024 15:26:12 +0100 Subject: Suggestion: A wiki page for all answered "Why don't you ...?" In-Reply-To: References: <033d2a24-3c6c-45f0-ac53-8bcb317322a5@oracle.com> Message-ID: On 2024-12-13 04:02, Ethan McCue wrote: > One practical trouble in assembling this is that the mailing lists > aren't exactly indexed/searchable. Yes, that is indeed annoying. :-( To be able to search locally on your own computer, you can download the archives using something like this: wget -l 0? --mirror --convert-links --no-parent https://mail.openjdk.org/pipermail/amber-dev/ This will give you all the mails as a -.txt file. Our CDN seems to be throttling wget, so you might have do to add something like "--user-agent=work-around-missing-searchable-archive" to the command line... > I'll make it my project to put something together by new years though. That's great to hear. Thank you Ethan! /Magnus > > On Fri, Dec 13, 2024, 6:26 AM Louis Wasserman wrote: > > Just seeing that it hasn't been mentioned, Guava's Idea Graveyard > is an example of this specific flavor of thing: > https://github.com/google/guava/wiki/IdeaGraveyard. (It's pretty > old, though, which reflects some of the downsides.) > > On Thu, Dec 12, 2024 at 10:34?AM Archie Cobbs > wrote: > > On Thu, Dec 12, 2024 at 10:07?AM Brian Goetz > wrote: > > There is the amber-docs repo which gets published to > `openjdk.org/projects/amber` > , which is probably a > better place to put it, and people can contribute via PRs. > > > I think putting something online under amber-docs is a great > idea - especially the part where people can contribute using > PR's, which fosters decentralized collaboration on the > maintenance of the list. > > While it would be ideal to have a complete directory of ideas > with accompanying summaries of all that has been discussed, we > should probably start with something simpler and more > maintainable. > > Here's a proposal: Have a list of "previously discussed > ideas". Each idea has a one line description, a one paragraph > summary, an optional example, and a bullet-point list of one > or more links to the thread(s) in the archive that contain all > the gory details of the discussion. > > Here's a simple example... > > *Idea:* Using switch statements for if/else control flow > > *Description:* Support "switches on nothing" where the cases > simply provide the conditions on which to execute various code > branches. > > *Example:* > > ??? public double toInches(String value) { > ??????? switch { > ??????? case when value.endsWith("mm") -> return 0.0393701 * > Integer.parseInt(value.substring(0, value.length() - 2)); > ??????? case when value.endsWith("ft") -> return 12 * > Integer.parseInt(value.substring(0, value.length() - 2)); > ??????? case when value.endsWith("light-years") ->?return > 3.725e+17 * Integer.parseInt(value.substring(0, value.length() > - 2)); > ??????? default -> throw new IllegalArgumentException("can't > parse value"); > ??????? } > ??? } > > *Discussion:* > > * https://mail.openjdk.org/pipermail/amber-dev/2024-October/008939.html > > > Just now seeing Eirik's reference to Project Jigsaw's Issue > Summary document. I like this even better but someone would > have to step up and take ownership. > > -Archie > > -- > Archie L. Cobbs > > > > -- > Louis Wasserman (he/they) > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fw at deneb.enyo.de Thu Dec 26 16:39:59 2024 From: fw at deneb.enyo.de (Florian Weimer) Date: Thu, 26 Dec 2024 17:39:59 +0100 Subject: Constructing records through reflection and module restrictions In-Reply-To: (Brian Goetz's message of "Mon, 9 Dec 2024 10:39:02 -0500") References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> <87r06if76t.fsf@mid.deneb.enyo.de> Message-ID: <87ldw2jt40.fsf@mid.deneb.enyo.de> * Brian Goetz: > There is a better approach than passing around the Lookup (which > requires everyone to coordinate around the Lookup capability): use open > modules.? THe concept of "open module" was designed for exactly this > purpose: to allow packages to be "exported for reflection" so that > frameworks can reflect over them more liberally than bytecode linkage > would permit.? If you put your domain objects in a package that is > opened (either to the framework, or to everyone), no need to play games > with Lookup. Open modules still require non-local types, increasing syntactic overhead considerably. My example > On 12/8/2024 11:52 AM, Florian Weimer wrote: >> * Remi Forax: >> >>>> Syntax-wise, it is very tempting to use this with very localized >>>> record types for various kinds of custom deserialization scenarios. >>>> For example, to read a CSV file with two colums, something like this >>>> could be used: >>>> >>>> record Row(String name, int index) {} >>>> var csv = CSVReader.newReader(r, Row.class); >>>> while (true) { >>>> var row = csv.readRow(); >>>> if (row == null) >>>> break; >>>> // Use the row variable. >>>> ... >>>> } was not exactly intended as shorthand notation (in the way in-line import directives are sometimes used in examples). I meant it quite literally, with actual local types. The record type syntax is so lightweight that it makes such code reasonable to write, I think. By the way, I find it confusing that MethodHandles.publicLookup() produces a method handle that can access open modules, while MethodHandles.lookup() does not. But maybe that's a bug in the way I configure the launcher. From fw at deneb.enyo.de Thu Dec 26 16:44:25 2024 From: fw at deneb.enyo.de (Florian Weimer) Date: Thu, 26 Dec 2024 17:44:25 +0100 Subject: Constructing records through reflection and module restrictions In-Reply-To: <876c222f-0c90-44c7-ba3b-d5f1f5280cf7@oracle.com> (Brian Goetz's message of "Mon, 9 Dec 2024 13:45:11 -0500") References: <87v7vv4ntl.fsf@mid.deneb.enyo.de> <6D305BE0-91A9-4261-87DB-56C7E1FCE86F@oracle.com> <87o71ngrir.fsf@mid.deneb.enyo.de> <242277097.17085797.1733610848446.JavaMail.zimbra@univ-eiffel.fr> <87r06if76t.fsf@mid.deneb.enyo.de> <876c222f-0c90-44c7-ba3b-d5f1f5280cf7@oracle.com> Message-ID: <87h66qjswm.fsf@mid.deneb.enyo.de> * Brian Goetz: > The `opens` clause of a module descriptor indeed can be qualified, just > as the exports clause can: > > ModuleDirective: > ??? requires {RequiresModifier} ModuleName ; > ??? exports PackageName [to ModuleName {, ModuleName}] ; > ??? opens PackageName [to ModuleName {, ModuleName}] ; > ??? uses TypeName ; > ??? provides TypeName with TypeName {, TypeName} ; I think the limitation here is that PackageName cannot be *. But opens ? to is problematic anyway because it breaks encapsulation. As far as I understand it, it is not transitive. So if a module changes its serialization provider, for example, opens ? to clauses would have to be adjusted to the new provider module. Even in clients of the changing module that do not know about the specific serialization provider being used. Passing around lookups avoids this issue. From david.1993grajales at gmail.com Sat Dec 28 04:14:41 2024 From: david.1993grajales at gmail.com (david Grajales) Date: Fri, 27 Dec 2024 23:14:41 -0500 Subject: sealed classes and interfaces can't permit classes or records from sub packages Message-ID: Hello Amber Team, I?ve observed a counter intuitive behavior, and I?m unsure whether it?s intentional or a potential issue. Here?s the scenario: 1. I have a package named vehicles containing a *sealed interface* called Vehicle. 2. Inside this vehicles package, I?ve created two sub-packages: - land-vehicles - water-vehicles 3. Each sub-package contains two records implementing the Vehicle interface. However, the compiler raises an error when I attempt this setup: "A class is not allowed to extend or implement a sealed class from another package." This seems counterintuitive because all components are conceptually part of the same package with the records merely placed in sub-packages for better organization. Here?s a textual representation of the package layout for reference: vehicles/ ??? Vehicle.java // Sealed interface ??? land-vehicles/ ? ??? Car.java // Record implementing Vehicle ? ??? Motorcycle.java // Record implementing Vehicle ??? water-vehicles/ ??? Boat.java // Record implementing Vehicle ??? Submarine.java // Record implementing Vehicle Could you clarify whether this behavior is intended or a bug? If not, could this be an area for potential improvement? I am using openjdk 23.0.1 Thank you for your time and assistance! Best regards and I hope you all have a nice new year. -------------- next part -------------- An HTML attachment was scrubbed... URL: From amaembo at gmail.com Sat Dec 28 06:23:56 2024 From: amaembo at gmail.com (Tagir Valeev) Date: Sat, 28 Dec 2024 07:23:56 +0100 Subject: sealed classes and interfaces can't permit classes or records from sub packages In-Reply-To: References: Message-ID: Hello! There's no such thing as a 'subpackage' in Java. Two packages having the same name prefix are just two different packages. If you want to group several packages together, a proper mechanism for this in Java is declaring a JPMS module. If you declare a module, you'll be able to put the implementations of your sealed interface into different packages within the module. With best regards, Tagir Valeev On Sat, Dec 28, 2024, 05:15 david Grajales wrote: > Hello Amber Team, > > I?ve observed a counter intuitive behavior, and I?m unsure whether it?s > intentional or a potential issue. > > Here?s the scenario: > > 1. I have a package named vehicles containing a *sealed interface* > called Vehicle. > 2. Inside this vehicles package, I?ve created two sub-packages: > - land-vehicles > - water-vehicles > 3. Each sub-package contains two records implementing the Vehicle > interface. > > However, the compiler raises an error when I attempt this setup: > > "A class is not allowed to extend or implement a sealed class from another > package." > > This seems counterintuitive because all components are conceptually part > of the same package with the records merely placed in sub-packages for > better organization. > > Here?s a textual representation of the package layout for reference: > > > vehicles/ > > ??? Vehicle.java // Sealed interface > > ??? land-vehicles/ > > ? ??? Car.java // Record implementing Vehicle > > ? ??? Motorcycle.java // Record implementing Vehicle > > ??? water-vehicles/ > > ??? Boat.java // Record implementing Vehicle > > ??? Submarine.java // Record implementing Vehicle > > > Could you clarify whether this behavior is intended or a bug? If not, > could this be an area for potential improvement? > > I am using openjdk 23.0.1 > > Thank you for your time and assistance! > > Best regards and I hope you all have a nice new year. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.1993grajales at gmail.com Sat Dec 28 12:23:23 2024 From: david.1993grajales at gmail.com (david Grajales) Date: Sat, 28 Dec 2024 07:23:23 -0500 Subject: sealed classes and interfaces can't permit classes or records from sub packages In-Reply-To: References: Message-ID: Thank you for the clarification and the workaround Tagir. Best regards! El s?b, 28 de dic de 2024, 1:24?a. m., Tagir Valeev escribi?: > Hello! > > There's no such thing as a 'subpackage' in Java. Two packages having the > same name prefix are just two different packages. If you want to group > several packages together, a proper mechanism for this in Java is declaring > a JPMS module. If you declare a module, you'll be able to put the > implementations of your sealed interface into different packages within the > module. > > With best regards, > Tagir Valeev > > On Sat, Dec 28, 2024, 05:15 david Grajales > wrote: > >> Hello Amber Team, >> >> I?ve observed a counter intuitive behavior, and I?m unsure whether it?s >> intentional or a potential issue. >> >> Here?s the scenario: >> >> 1. I have a package named vehicles containing a *sealed interface* >> called Vehicle. >> 2. Inside this vehicles package, I?ve created two sub-packages: >> - land-vehicles >> - water-vehicles >> 3. Each sub-package contains two records implementing the Vehicle >> interface. >> >> However, the compiler raises an error when I attempt this setup: >> >> "A class is not allowed to extend or implement a sealed class from >> another package." >> >> This seems counterintuitive because all components are conceptually part >> of the same package with the records merely placed in sub-packages for >> better organization. >> >> Here?s a textual representation of the package layout for reference: >> >> >> vehicles/ >> >> ??? Vehicle.java // Sealed interface >> >> ??? land-vehicles/ >> >> ? ??? Car.java // Record implementing Vehicle >> >> ? ??? Motorcycle.java // Record implementing Vehicle >> >> ??? water-vehicles/ >> >> ??? Boat.java // Record implementing Vehicle >> >> ??? Submarine.java // Record implementing Vehicle >> >> >> Could you clarify whether this behavior is intended or a bug? If not, >> could this be an area for potential improvement? >> >> I am using openjdk 23.0.1 >> >> Thank you for your time and assistance! >> >> Best regards and I hope you all have a nice new year. >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: