Hyperlinkv0.8.0-beta.28

Stream

Stream.mapAccumconsteffect/Stream.ts:7424
<S, A, B>(
  initial: LazyArg<S>,
  f: (s: S, a: A) => readonly [state: S, values: ReadonlyArray<B>],
  options?: {
    readonly onHalt?: ((state: S) => ReadonlyArray<B>) | undefined
  }
): <E, R>(self: Stream<A, E, R>) => Stream<B, E, R>
<A, E, R, S, B>(
  self: Stream<A, E, R>,
  initial: LazyArg<S>,
  f: (s: S, a: A) => readonly [state: S, values: ReadonlyArray<B>],
  options?: {
    readonly onHalt?: ((state: S) => ReadonlyArray<B>) | undefined
  }
): Stream<B, E, R>

Maps elements statefully, emitting zero or more outputs per input.

Example (Statefully mapping stream values)

import { Console, Effect, Stream } from "effect"

const program = Effect.gen(function*() {
  const totals = yield* Stream.make(0, 1, 2, 3, 4, 5, 6).pipe(
    Stream.mapAccum(() => 0, (total, n) => {
      const next = total + n
      return [next, [next]] as const
    }),
    Stream.runCollect
  )

  yield* Console.log(totals)
})

Effect.runPromise(program)
// Output: [ 0, 1, 3, 6, 10, 15, 21 ]
mapping
Source effect/Stream.ts:742445 lines
export const mapAccum: {
  <S, A, B>(
    initial: LazyArg<S>,
    f: (s: S, a: A) => readonly [state: S, values: ReadonlyArray<B>],
    options?: {
      readonly onHalt?: ((state: S) => ReadonlyArray<B>) | undefined
    }
  ): <E, R>(self: Stream<A, E, R>) => Stream<B, E, R>
  <A, E, R, S, B>(
    self: Stream<A, E, R>,
    initial: LazyArg<S>,
    f: (s: S, a: A) => readonly [state: S, values: ReadonlyArray<B>],
    options?: {
      readonly onHalt?: ((state: S) => ReadonlyArray<B>) | undefined
    }
  ): Stream<B, E, R>
} = dual((args) => isStream(args[0]), <A, E, R, S, B>(
  self: Stream<A, E, R>,
  initial: LazyArg<S>,
  f: (s: S, a: A) => readonly [state: S, values: ReadonlyArray<B>],
  options?: {
    readonly onHalt?: ((state: S) => ReadonlyArray<B>) | undefined
  }
): Stream<B, E, R> =>
  fromChannel(Channel.mapAccum(
    self.channel,
    initial,
    (state, arr) => {
      const acc = Arr.empty<B>()
      for (let index = 0; index < arr.length; index++) {
        const [newState, values] = f(state, arr[index])
        state = newState
        acc.push(...values)
      }
      return [state, Arr.isArrayNonEmpty(acc) ? Arr.of(acc) : emptyArr]
    },
    options?.onHalt ?
      {
        onHalt(state) {
          const arr = options.onHalt!(state)
          return Arr.isReadonlyArrayNonEmpty(arr) ? Arr.of(arr) : emptyArr
        }
      } :
      undefined
  )))