Hi mg,
It should probably just say "It" instead of "Path A". I had a much longer
example and asked AI to help summarise it.
So here, when you use `Files.lines(path).withCloseable { src -> ... }` and
destructure like `def (header, *body) = src`, the `body` variable is still
a lazy Stream. If that stream is consumed, the underlying file handle is
closed correctly.
Or another way, it avoids bringing the whole file into memory just to
process (or not) the body.
Cheers, Paul.
On Wed, Apr 29, 2026 at 2:06 AM MG <[email protected]> wrote:
> Hi Paul,
>
> what is "Path A keeps the Stream lazy and propagates onClose -- the killer
> demo for the streaming contract." supposed to mean ?
>
> Cheers,
> mg
>
> Am 27.04.2026 um 13:39 schrieb Paul King:
>
> 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.
>
>
>