Hi there, I am probably missing something obvious here, but why adding separate methods for this instead of simply reusing asType?
Thanks and all the best, OC > On 2. 11. 2021, at 8:35, Paul King <pa...@asert.com.au> wrote: > > Thanks for the feedback! I added "toMap()" to the PR. > > On Tue, Nov 2, 2021 at 7:02 AM MG <mg...@arscreat.com> wrote: >> >> Hi Paul, >> >> quick "from the top of my head" reply: >> >> copyWith(...): Sounds like a great idea, I have record-like classes in use, >> and the need for something like this arises immediately in practice >> getAt(int): Don't see why not, might be useful >> toList(): Destructuring should show its strength when pattern matching is >> introduced - outside of pattern matching right now I don't see much >> application/need for such functionality (but would be interested to see some >> practical examples :-) ), but having it does not seem to hurt. >> components(): Same as getAt; the name seems quite long, maybe we can come up >> with something more terse ? >> toMap(): If we have toList(), would a toMap() make sense, so that the map >> could be modified and passed as a record ctor argument to create a new >> record ? >> >> Cheers, >> mg >> >> >> On 01/11/2021 16:14, Paul King wrote: >> >> Hi folks, >> >> I will be ready for a new Groovy 4 release shortly. I am interested in >> folks' thoughts on records as they have gone through a few changes >> recently (documented in [1], [2] and [3]) and there is a proposal[4] >> for a few more enhancements. >> >> There is a "copyWith" method (still undergoing some refactoring) >> similar to the copy method in Scala and Kotlin which allows one record >> to be defined in terms of another. It can be disabled if you really >> must have Java-like records. The refactoring of that method hit a >> slight glitch, so might not work if you grab the latest source but >> should be fixed shortly. >> >> record Fruit(String name, double price) {} >> def apple = new Fruit('Apple', 11.6) >> assert apply.toString() == 'Fruit[name=Apple, price=11.6]' >> def orange = apple.copyWith(name: 'Orange') >> assert orange.toString() == 'Fruit[name=Orange, price=11.6]' >> >> There is a "getAt(int)" method to return e.g. the first component with >> myRecord[0] following similar Groovy conventions for other aggregates. >> This is mostly targeted at dynamic Groovy as it conveys no typing >> information. Similarly, there is a "toList" (current name but >> suggestions welcome) method which returns a Tuple (which is also a >> list) to return all of the components (again with typing information). >> >> record Point(int x, int y, String color) {} >> def p = new Point(100, 200, 'green') >> assert p[0] == 100 >> assert p[1] == 200 >> assert p[2] == 'green' >> def (x, y, c) = p.toList() >> assert x == 100 >> assert y == 200 >> assert c == 'green' >> >> There is also an optional (turned on by an annotation attribute) >> "components" method which returns all components as a typed tuple, >> e.g. Tuple1, Tuple2, etc. This is useful for Groovy's static nature >> and is automatically handled by current destructuring (see the tests >> in the PR). The limitation is that we currently only go to Tuple16 >> with our tuple types - which is why I made it disabled by default. >> >> @RecordBase(componentTuple=true) >> record Point(int x, int y, String color) { } >> >> @TypeChecked >> def method() { >> def p1 = new Point(100, 200, 'green') >> def (int x1, int y1, String c1) = p1.components() >> assert x1 == 100 >> assert y1 == 200 >> assert c1 == 'green' >> >> def p2 = new Point(10, 20, 'blue') >> def (x2, y2, c2) = p2.components() >> assert x2 * 10 == 100 >> assert y2 ** 2 == 400 >> assert c2.toUpperCase() == 'BLUE' >> } >> >> An alternative would be to follow Kotlin's approach and just have >> typed methods like "component1", "component2", etc. We might want to >> follow that convention or we might want to follow our TupleN naming, >> e.g. "getV1", "getV2", etc. We would need to augment the Groovy >> runtime and type checker to know about records if we wanted to support >> destructuring but we could avoid the "toList" method and "components" >> method with its size limitation if we did add such support. >> >> Any feedback welcome, >> >> Cheers, Paul. >> P.S. Records are an incubating feature - hence may change in backwards >> incompatible ways, particularly until we hit Groovy 4 final. >> >> [1] https://github.com/apache/groovy/blob/master/src/spec/doc/_records.adoc >> [2] >> https://github.com/apache/groovy/blob/master/src/spec/test/RecordSpecificationTest.groovy >> [3] >> https://github.com/apache/groovy-website/blob/asf-site/site/src/site/wiki/GEP-14.adoc >> [4] https://issues.apache.org/jira/browse/GROOVY-10338 >> >>