Countdown
Countdown is an endomorphic stage that passes its input through for exactly n invocations and then
signals pipeline completion. On each of the first n − 1 calls it yields Status.Success; on the n-th
call it yields Status.Complete and the next generation resets to n, ready to count down again.
Countdown is fully immutable: each state transition creates a new instance rather than mutating the current one.
The factory Countdown(n) is the normal entry point. If n ≤ 0 it returns DeadEnd instead,
ensuring the returned stage is always safe to use.
import h8io.stages.*
import h8io.stages.std.*
val c = Countdown[String](3)
// c: Stage.Endo[String, Nothing] = Countdown(i = 3L, n = 3L)
val y1 = c("a")
// y1: Yield[String, String, Nothing] = Some(
// out = "a",
// status = Success,
// evolution = h8io.stages.std.Countdown$$anon$1@50ccbb5b
// )
val y2 = y1.evolve()("b")
// y2: Yield[String, String, Nothing] = Some(
// out = "b",
// status = Success,
// evolution = h8io.stages.std.Countdown$$anon$1@54f3359a
// )
val y3 = y2.evolve()("c")
// y3: Yield[String, String, Nothing] = Some(
// out = "c",
// status = Complete(),
// evolution = ConstEvolution(
// stage = Countdown(i = 3L, n = 3L),
// _dispose = h8io.stages.base.ConstEvolution$$$Lambda$14325/0x00007f2c92621d60@4bfbbb9
// )
// )
y1 and y2 carry Status.Success; y3 carries Status.Complete. Calling y3.evolve() returns a fresh
Countdown(3) that is ready to count down again.