In any case, I created a draft PR and some interesting points came up which I think deserve more discussion.
https://github.com/apache/groovy/pull/2182 I have marked all of the methods as @Incubating for now, in case we want to merge and tweak later. What's in the PR? I went with the "Lazy" naming suggestion. As proposed, I did findAllLazy, collectLazy and collectManyLazy (these are just for Iterator in/out variants). I also checked for other candidates which could have this treatment. I think there are only three. I did implementations for collectEntriesLazy and findIndexValuesLazy but have left findResultsLazy for now (it's easy to add). When coding these, I experimented with the approach Groovy-stream takes of setting the delegate in the relevant closures. We have traditionally done this for tap/with but not generally otherwise. I'll add some examples of the benefits in the related Jira issue: https://issues.apache.org/jira/browse/GROOVY-11606 For now, I have also added map, flatMap and filter (just for Iterators) that instead of using a Closure, use the Functions and Predicates. These don't set the delegate. For now, these let us compare and contrast the different approaches and try out some performance measurements. Unless they prove much faster, or we really like the idea of them as familiar aliases, I'd expect them to be removed before Groovy 5 goes GA. I wasn't thinking we'd provide aliases for non-Iterator variants. Paul. On Wed, Apr 9, 2025 at 11:25 AM Paul King <pa...@asert.com.au> 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. > > 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. > > 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? > > 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. > > 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. > > Thoughts? > > Paul. > > > [1] https://github.com/timyates/groovy-stream > [2] https://github.com/tginsberg/gatherers4j