On Thu, Apr 10, 2025 at 1:49 AM Milles, Eric (TR Technology) via dev <dev@groovy.apache.org> wrote: > > My general concern is the number of overloads and variants.
Yes, maybe we break compatibility for Groovy 5 and just keep the current names. That would keep name overloads/maintenance down. I think with gatherers becoming more familiar and virtual threads, having lazy options will become more commonplace. If we ever wanted to refresh Gpars with virtual threads, having a clean slate would be a good thing. > collect, collectMany and findAll would probably be named something else if > created anew today. Adding to this creates confusion IMO. Do you have a > Java stream and Groovy as-is version to compare against for each proposed new > method? It helps me at least to see what it would take to do the same > without the extension. You probably need a library like Gatherers4j in combination with normal streams to cover off all the methods. That was in fact what kick-started the journey I have been on for the last few weeks. I have a blog post which does just that. I stopped working on it when these issues came up. I'll revamp and send in its current raw form, though it's not quite ready for publication. Paul. > ________________________________ > From: Jochen Theodorou <blackd...@gmx.org> > Sent: Wednesday, April 9, 2025 6:21 AM > To: dev@groovy.apache.org <dev@groovy.apache.org> > Subject: [EXT] Re: [DISCUSS] Lazy findAll, collect, collectMany > > External Email: Use caution with links and attachments. > > On 09.04.25 03:25, Paul King wrote: > > Hi folks, > > > > [I sent this to grails dev list but meant to send it here and CC them > > for feedback - anyway, it is here now, apologies if you see this > > twice.] > > > > I have been looking at the functionality in Groovy-stream[1] and > > Gatherers4J[2] lately with a view to filling any gaps in Groovy's > > iterator DGM methods. I'm not trying to replicate everything they > > contain, just looking for the most useful functionality Groovy might > > be missing. > > > > The biggest missing pieces at this point in my mind are lazy (Iterator > > return value) variants of findAll, collect, and collectMany. Groovy's > > current variants are eager (return collections and lists). > > Groovy-stream gets around this by adding stream-named variants: > > filter, map, and flatMap. > > > does Iterator really automatically mean lazy? Is this possible then? > > def l = [1,2,3] > def iterator = l.iterator().findAll{it>1} > l[0] = 20 > assert iterator.toList() == [20,2,3] > > The combination of lazy and mutable can be problematic. Also, can I do > iterator.toList() multiple times? > > > One option is to break backwards compatibility (Groovy 5 only). So > > only for the versions of those methods which take an Iterator as > > input, change the return type to be Iterator. Given how widely used > > those methods are, I don't think that is an option for us. > > well... we could have lazyIt() which return a LazyIterator. that would > make things clear. > > > Actually, findAll currently doesn't have an Iterator variant, so we > > could add that but it would still be a behavioral compatibility > > breakage since the Object version is used for Iterators and it returns > > a list. > > > > So, we could give up on lazy variants for those methods, but again > > given how commonly used they are, that is a pretty big gap. > > > > So, the other option is to provide alternative names. The best to me seem: > > > > (A) findAllLazy, collectLazy, collectManyLazy > > (B) findAllThen, collectThen, collectManyThen > > (C) filter, map, flatMap > > (D) something else? > > (E) lazyIt() > > I am pretty sure it will not be considered as because it is a bit > ugly... but frankly I am no fan of A at all for the very same reason. B > I find more nice because it is more semantics based. > > hmm... what happens if you mix lazy and non-lazy... like for example > findAllthen(...).findAll(...) > > > Option (C) is what Groovy-stream did and would be familiar to Java > > Stream users but folks are going to ask, why can't I have that "alias" > > for Iterables and arrays, but the intent here is just for the Iterator > > variants. I think Lazy best conveys that. Use without "Lazy" for the > > eager (think terminal operator) variant and with "Lazy" for the lazy > > (think intermediate operator) variant. It also is easier to extend, > > the fourth method in terms of gaps is collectEntries, which currently > > returns a Map. An Iterator<Map.Entry> return value could be made for > > collectEntriesLazy if we wanted. > > somehow does not really convince me all. > > > Note that many of our operators are terminal in nature, find, count*, > > inject, etc, so this isn't about doing this for all operators > > eventually. > > but findAllThen does not come over as terminal. If they are supposed to, > then I don't find the names fitting in the cases of A and B. > > bye jochen >