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.