| 1252 | predicate: Predicate<S>, |
| 1253 | f: (s: S, input: In) => S |
| 1254 | ): Sink<S, In, In> => |
| 1255 | fromTransform((upstream) => { |
| 1256 | let state = initial() |
| 1257 | let leftover: NonEmptyReadonlyArray<In> | undefined = undefined |
| 1258 | if (!predicate(state)) { |
| 1259 | return Effect.succeed([state] as const) |
| 1260 | } |
| 1261 | return upstream.pipe( |
| 1262 | Effect.flatMap((arr) => { |
| 1263 | for (let i = 0; i < arr.length; i++) { |
| 1264 | state = f(state, arr[i]) |
| 1265 | if (!predicate(state)) { |
| 1266 | if ((i + 1) < arr.length) { |
| 1267 | leftover = arr.slice(i + 1) as any |
| 1268 | } |
| 1269 | return Cause.done() |
| 1270 | } |
| 1271 | } |
| 1272 | return Effect.void |
| 1273 | }), |
| 1274 | Effect.forever({ disableYield: true }), |
| 1275 | Pull.catchDone(() => Effect.succeed([state, leftover] as const)) |
| 1276 | ) |
| 1277 | }) |
| 1278 | |
| 1279 | /** |
| 1280 | * A sink that effectfully reduces input elements from the provided `initial` |
| 1281 | * state with `f` while the specified `predicate` returns `true`. |
| 1282 | * |
| 1283 | * @category folding |
| 1284 | * @since 4.0.0 |
| 1285 | */ |
| 1286 | export const reduceWhileEffect = <S, In, E, R>( |
| 1287 | initial: LazyArg<S>, |
| 1288 | predicate: Predicate<S>, |
| 1289 | f: (s: S, input: In) => Effect.Effect<S, E, R> |