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
>
>

Reply via email to