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

Reply via email to