cycle

Emite una secuencia y luego la repite — para siempre. Combínala siempre con un límite como take.

Iterable<T> cycle<T>(Iterable<T> iterable) FxAsyncIterable<T> cycleAsync<T>(FxAsyncIterable<T> iterable) Fx<T> Fx.cycle() // chain FxAsync<T> FxAsync.cycle()

Lección

cycle es infinito: reproduce la secuencia fuente una vez, guardando sus valores en un búfer sobre la marcha, y después recorre ese búfer en bucle para siempre. A diferencia de todo lo demás en esta sección, cycle nunca se agota por su cuenta — siempre tienes que combinarlo con algo que decida cuándo parar, casi siempre .take(n). Llamar a toList() o a consume() directamente sobre un cycle(...) pelado sin un límite en medio se quedará colgado.

Un caso límite que conviene conocer: ciclar una fuente vacía no emite nada en absoluto, en lugar de dar vueltas eternamente sobre cero elementos — así que cycle([]) es seguro y simplemente produce un resultado vacío.

Es una pieza natural para el reparto round-robin (recorrer en ciclo una lista corta de trabajadores/colores/huecos mientras haces map sobre una más larga) o para repetir una secuencia asíncrona corta y modelar así un bucle de sondeo. La forma asíncrona, cycleAsync (o .cycle() en una cadena FxAsync), hace el búfer y el bucle igual, pero tira de cada vuelta a través del protocolo asíncrono habitual.

Demo 1 · Infinito, acotado con take

Demo 2 · Ciclo asíncrono, también acotado con take

Pruébalo tú

Ejercicio: recorre en ciclo los colores de un semáforo y toma los 8 primeros.

Relacionado: range — una secuencia de conteo finita · repeat — repite un único valor, un número fijo de veces · take — el límite que cycle casi siempre necesita · concurrent — solapa el trabajo de un cycle asíncrono