Re: features for groovy-6.0.0-alpha-1

Jochen Theodorou <[email protected]> Thu, 30 Apr 2026 17:36:21 +0200
Newsgroups gmane.comp.lang.groovy.devel
Message-ID <[email protected]>
actually one question regarding GPars features.

Afaik you could do urls.collectParallel{...}, but also 
urls.parallel.collect{...}.

I guess it was excluded because of getParallel() as "Legacy JSR-166 
ParallelArray API; obsolete since Java 8 streams"

But I see this more as a DSL choice, then depending on a feature. I 
personally like urls.parallel().collect most, then urls.parallel.collect 
and only on last place urls.collectParallel. Frankly I would have even 
expected urls.parallelCollect, if I had seen it for the first time.

To be more specific.. assume you have

def findOkUrls(urls) {
    urls.collect { fetch(it) }
        .findAll { it.status == 200 }
        .groupBy { it.host }
}
findOkUrls(myUrls)

and then you could replace that with

def findOkUrls(urls) {
    urls.collect { fetch(it) }
        .findAll { it.status == 200 }
        .groupBy { it.host }
}

ParallelScope.withPool(Pool.cpu()) {
   findOkUrls(myUrls)
}

Meaning not touching the method itself.

bye Jochen

On 4/30/26 05:37, Paul King wrote:
> I have merged the GPars-related functionality. I'll tidy the docs but 
> shout if you spot any problems.
> 
> Cheers, Paul.
> 
> On Mon, Apr 27, 2026 at 9:39 PM Paul King <[email protected] 
> <mailto:[email protected]>> wrote:
> 
>     Hi folks,
> 
>     I believe the following features are ready for inclusion in Groovy
>     6.0.0-alpha-1.
>     Please see the relevant PRs and Jira issues for more information.
> 
>     Feedback, as always, is welcome.
> 
>     Cheers, Paul.
> 
>     GEP-18 -- Ported GPars features
>     ================================
> 
>     1. Parallel collections inside a scope -- drop-in speedup
> 
>          ParallelScope.withPool(Pool.cpu()) {
>              urls.collectParallel { fetch(it) }
>                  .findAllParallel { it.status == 200 }
>                  .groupByParallel { it.host }
>          }
> 
>         Familiar GPars xxxParallel names, pool-isolated and
>         virtual-thread-ready.
> 
>     2. Dataflows -- orchestration by data dependency, not thread
>         choreography
> 
>          def df = new Dataflows()
>          async { df.result = combine(df.user, df.prefs) }
>          async { df.user  = loadUser(id) }
>          async { df.prefs = loadPrefs(id) }
>          println await(df.result)
> 
>         The order in source is irrelevant; readers block until the
>         writers bind. Reads as plainly as sequential code.
> 
>     But also, actors/active objects, agents and channels.
> 
>     GEP-20 -- Additional multi-assignment forms
>     ============================================
> 
>     1. Tail rest against a Stream -- head/body split with no
>         materialisation
> 
>          Files.lines(path).withCloseable { src ->
>              def (header, *body) = src
>              body.filter { !it.isBlank() }.forEach { process(it) }
>          }
> 
>         Path A keeps the Stream lazy and propagates onClose -- the
>         killer demo for the streaming contract.
> 
>     2. Head and middle rest -- edge-aware slicing in one line
> 
>          def (first, *middle, last) = readings    // peel both ends
>          def (l, *m, r)             = segment     // boundary + interior
> 
>         Replaces [0] / [1..-2] / [-1] boilerplate that's surprisingly
>         common.
> 
>     3. Map-style destructuring -- beans and config in one shot
> 
>          def (host: h, port: p, name: n) = config
>          def (name: String fullName, age: int a) = person
> 
>         Works against Map, beans, and GroovyObject uniformly via the
>         MOP -- the rename form (name: fullName) is a quiet bonus.
> 
> 
>     When assessing GEP-20, bear in mind the very early draft for GEP-19
>     targetted tentatively for Groovy 7.
> 
>     GEP-19 -- Structural pattern matching in switch
>     ================================================
> 
>     1. Recursive list algorithm in its canonical functional shape
> 
>          def sum(xs) {
>              switch (xs) {
>                  case []                -> 0
>                  case [var h, var... t] -> h + sum(t)
>              }
>          }
> 
>         The motivating example -- what you can't write tidily today.
> 
>     2. Map patterns for tagged-shape dispatch (events, JSON, configs)
> 
>          switch (event) {
>              case [type: 'click',  x: var x, y: var y] -> handleClick(x, y)
>              case [type: 'key',    code: var k]        -> handleKey(k)
>              case [type: 'scroll', ...]                -> redraw()
>          }
> 
>         Open semantics plus rest binding makes this read like a
>         protocol spec.
> 
>     3. Type pattern + record pattern + guard -- visitor replacement
> 
>          switch (shape) {
>              case Circle c when c.radius > 0 -> Math.PI * c.radius**2
>              case Rect(int w, int h)         -> w * h
>              case Line(_, Point p2)          -> "ends at $p2"
>              default                         -> 0
>          }
> 
>         One construct subsumes instanceof chains, accessor calls, and
>         the constraint check.
>