scan

Una acumulación progresiva y perezosa — como reduce, pero emite todos los valores intermedios en lugar de solo el último.

Iterable<B> scan<A, B>(B Function(B acc, A a) f, B seed, Iterable<A> iterable) Iterable<A> scan1<A>(A Function(A acc, A a) f, Iterable<A> iterable) FxAsyncIterable<B> scanAsync<A, B>(FutureOr<B> Function(B acc, A a) f, FutureOr<B> seed, FxAsyncIterable<A> iterable) FxAsyncIterable<A> scan1Async<A>(FutureOr<A> Function(A acc, A a) f, FxAsyncIterable<A> iterable) Fx<B> Fx.scan<B>(B Function(B acc, T a) f, B seed) // chain FxAsync<B> FxAsync.scan<B>(FutureOr<B> Function(B acc, T a) f, FutureOr<B> seed) FxEvents<R> FxEvents<T>.scan<R>(R Function(R acc, T a) f, R seed) // chain (events)

Lección

scan es reduce/fold con sus pasos intermedios a la vista: en lugar de colapsar un iterable en un único valor final, emite todas las acumulaciones parciales, incluido el propio valor inicial como primer valor. Ese detalle —que el primer valor es el valor inicial— importa: scan(f, 0, [1, 2, 3]) emite cuatro valores (0 y luego tres sumas parciales), no tres.

scan1 es la variante sin valor inicial, portada de la sobrecarga scan(f, iterable) de FxTS (sin argumento de valor inicial). Usa el primer elemento del iterable como acumulador inicial y lo emite de inmediato, y luego sigue plegando el resto, reflejando la relación de reduce con fold. Sobre un iterable vacío, scan1 no tiene primer elemento con el que arrancar, así que no emite nada en absoluto. Ten en cuenta que no hay método de cadena para scan1 (solo scan está en Fx/FxAsync): llámalo en forma data-first, scan1(f, iterable).

Ambos son perezosos: no se ejecuta nada hasta que tiras de los valores. En el lado asíncrono, scanAsync/scan1Async siguen plegando paso a paso y en orden (cada paso necesita el resultado anterior), así que .concurrent(n) no paraleliza el pliegue en sí; lo que sí hace es permitir que una etapa de descarga aguas arriba se ejecute con concurrencia, siempre que la propia función acumuladora sea barata. Mira la Demo 2.

Demo 1 · Fundamentos — scan y scan1

Demo 2 · Asíncrono, con concurrencia aguas arriba

El pliegue en sí sigue siendo secuencial, pero la descarga que lo alimenta no tiene por qué serlo:

Pruébalo tú

Ejercicio: usa scan para producir un total acumulado de pasos, con 0 como valor inicial.

Relacionado: reduce/fold — colapsa a un único valor final · flat — aplana iterables anidados · peek — observa sin transformar · concurrent — evaluación paralela