As for tersity, I presume the actual usage would look like „foo as Map“ or „foo 
as List“ anyway, which is actually one less keypress :), and — which in my 
personal opinion is considerably more important — it offers better consistency 
and polymorphism.

(I know next to nothing of Intellisense, but I guess it should offer the as 
operator with a selection of known types, should it not?)

Still I might be missing something of importance, of course.

All the best,
OC

> On 2 Nov 2021, at 19:17, MG <mg...@arscreat.com> wrote:
> 
> Hmmm, yes, that would be an option.
> More terse & can be discovered via Intellisense are two reasons I could think 
> of that speak for the toList()/toMap() approach...
> 
> Cheers,
> mg
> 
> On 02/11/2021 12:48, OCsite wrote:
>> 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