> De: "John Rose" <[email protected]> > À: "Remi Forax" <[email protected]> > Cc: "Peter Levart" <[email protected]>, "Rémi Forax" > <[email protected]>, "core-libs-dev" <[email protected]> > Envoyé: Vendredi 4 Juin 2021 02:05:41 > Objet: Re: [External] : Re: RFR: 8199318: add idempotent copy operation for > Map.Entry
> On Jun 3, 2021, at 3:17 PM, [ mailto:[email protected] | [email protected] ] > wrote: >>> De: "John Rose" <john. [ mailto:[email protected] | [email protected] ] > >>> À: "Remi Forax" < [ mailto:[email protected] | [email protected] ] > >>> Cc: "Peter Levart" < [ mailto:[email protected] | >>> [email protected] ] >>> >, "Rémi Forax" < [ mailto:[email protected] | [email protected] >>> >] >, >>> "core-libs-dev" < [ mailto:[email protected] | >>> [email protected] ] > >>> Envoyé: Jeudi 3 Juin 2021 22:51:28 >>> Objet: Re: RFR: 8199318: add idempotent copy operation for Map.Entry >>> ... >>> interface ComparableRecord<T extends Record & ComparableRecord<T>> >>> extends Comparable<T> { … } >>> record Foo(int x, String y) implements ComparableRecord<Foo> { … } >>> [ http://cr.openjdk.java.net/~jrose/draft/ComparableRecord.java | >>> http://cr.openjdk.java.net/~jrose/draft/ComparableRecord.java ] >> [repost with a link] >> The main issue with this kind of code is that the JIT does not see through >> the >> ClassValue. > Wow, it’s almost as if we’ve discussed this already! ;-) > So, [ https://bugs.openjdk.java.net/browse/JDK-8238260 | > https://bugs.openjdk.java.net/browse/JDK-8238260 ] > Part of my agenda here is finding more reasons why > JDK-8238260 deserves some love. > Currently, the translation strategy for Records > requires a lot of boilerplate generated into each > subclass for toString, equals, and hashCode. > It is partially declarative, because it uses indy. > So, yay for that. But it is also a bad smell (IMO) > that the trick needs to be played in each subclass. > If ClassValue were performant, we could have > just one method in Record for each of toString, > equals, and hashCode, and have them DTRT. > The user code would then be able to call > super.toString() to get the standard behavior > in a refining wrapper method in a subclass. > Looking further, it would be nice to have methods > which (a) inherit from supers as reusable code > ought to, but (b) re-specialize themselves once > per subclass indy-style. This is a VM trick I hope > to look into after we do specialization. For now, > ClassValue is the way to simulate that. yes, it's a specialization problem. I wonder if it an be resolved using a combination of a species-static variable and magic shibboleth to ask the type parameter to be always reified interface ComparableRecord <please-always-reified-me T extends Record & ComparableRecord< T > > extends Comparable< T > { species-static Comparator<T> COMPARATOR; // a parameteric condy ? species-static { COMPARATOR = ... } default int compareTo(T other) { return COMPARATOR.compare(this, other); } } >> Tweaking a little bit your code, I get >> [ >> https://urldefense.com/v3/__https://gist.github.com/forax/e76367e1a90bf011692ee9bec65ff0f8__;!!GqivPVa7Brio!MheW9rHDHXlXYNKUju7v5G0vXlpj1YOoDWFjG9AcpnXnVz2TxlMYDM7i86yFtT_B$ >> | https://gist.github.com/forax/e76367e1a90bf011692ee9bec65ff0f8 ] >> (It's a PITA that we have to use a raw type to workaround circularly defined >> parameter type) > I tried to DTRT and got into Inference Hell, surrounded > by a swarms of unfriendly wildcards with pitchforks. > Glad it wasn’t just me. > Inspired by your more whole-hearted use of streams > to build the code, I updated my example. Thanks. > — John Rémi
