Add input support to generate (#14804)

- closes #8523 

# Description

This PR adds pipeline input support to `generate`.
- Without input, `generate` keeps its current behavior.
- With input, each invocation of the closure is provided an item from
the input stream as pipeline input (`$in`). If/when the input stream
runs out, `generate` also stops.

Before this PR, there is no filter command that is both stateful _and_
streaming.

This PR also refactors `std/iter scan` to use `generate`, making it
streaming and more performant over larger inputs.

# User-Facing Changes
- `generate` now supports pipeline input, passing each element to the
closure as `$in` until it runs out
- `std/iter scan` is now streaming

# Tests + Formatting
Added tests to validate the new feature.

- 🟢 toolkit fmt
- 🟢 toolkit clippy
- 🟢 toolkit test
- 🟢 toolkit test stdlib

# After Submitting
N/A
This commit is contained in:
Bahex
2025-01-14 20:44:31 +03:00
committed by GitHub
parent 306e305b65
commit 301d1370c4
3 changed files with 178 additions and 102 deletions

View File

@ -107,16 +107,12 @@ export def scan [ # -> list<any>
init: any # initial value to seed the initial state
fn: closure # the closure to perform the scan
--noinit(-n) # remove the initial value from the result
] {
reduce --fold [$init] {|e, acc|
let acc_last = $acc | last
$acc ++ [($acc_last | do $fn $e $acc_last)]
}
| if $noinit {
$in | skip
} else {
$in
}
] {
generate {|e, acc|
let out = $acc | do $fn $e $acc
{next: $out, out: $out}
} $init
| if not $noinit { prepend $init } else { }
}
# Returns a list of values for which the supplied closure does not