UNPKG

lfi

Version:

A lazy functional iteration library supporting sync, async, and concurrent iteration.

1,405 lines (1,345 loc) 207 kB
//#region src/internal/types.d.ts /** @internal */ type MaybePromiseLike<Value> = Value | PromiseLike<Value>; /** @internal */ type StrictNegative<Numeric extends number> = Numeric extends 0 ? never : `${Numeric}` extends `-${string}` ? Numeric : never; /** @internal */ /** @internal */ type NonNegative<Numeric extends number> = Numeric extends 0 ? Numeric : StrictNegative<Numeric> extends never ? Numeric : never; /** @internal */ type StrictInteger<Numeric extends number> = `${Numeric}` extends `${bigint}` ? Numeric : never; /** @internal */ type CheckNumericLiteral<Numeric extends number, LiteralNumber extends number> = number extends Numeric ? Numeric : LiteralNumber; /** @internal */ type Integer<Numeric extends number> = CheckNumericLiteral<Numeric, StrictInteger<Numeric>>; /** @internal */ type NonNegativeInteger<Numeric extends number> = CheckNumericLiteral<Numeric, NonNegative<StrictInteger<Numeric>>>; /** @internal */ type PositiveInteger<Numeric extends number> = CheckNumericLiteral<Numeric, NonNegative<StrictInteger<Numeric>>>; //#endregion //#region src/operations/core.d.ts /** @internal */ type Curried<Parameters extends readonly any[], Return> = <PartialParameters extends Partial<Parameters>>(...args: PartialParameters) => PartialParameters extends Parameters ? Return : Parameters extends readonly [...TupleOfSameLength<PartialParameters>, ...infer RemainingParameters] ? RemainingParameters extends any[] ? Curried<RemainingParameters, Return> : never : never; /** @internal */ type TupleOfSameLength<Tuple extends readonly any[]> = Extract<{ [Key in keyof Tuple]: any }, readonly any[]>; /** * Returns a [curried](https://lfi.dev/docs/concepts/currying) version of `fn`. * * @example * ```js playground * import { curry } from 'lfi' * * function slothLog(a, b, c) { * console.log(`${a} Sloth ${b} Sloth ${c}`) * } * * const curriedSlothLog = curry(slothLog) * * console.log(curriedSlothLog.name) * //=> slothLog * * console.log(curriedSlothLog.length) * //=> 3 * * curriedSlothLog(`Hello`, `World`, `!`) * curriedSlothLog(`Hello`)(`World`, `!`) * curriedSlothLog(`Hello`, `World`)(`!`) * curriedSlothLog(`Hello`)(`World`)(`!`) * //=> Hello Sloth World Sloth ! * //=> Hello Sloth World Sloth ! * //=> Hello Sloth World Sloth ! * //=> Hello Sloth World Sloth ! * ``` * * @category Core * @since v0.0.1 */ declare const curry: <Parameters extends readonly any[], Return>(fn: (...args: Parameters) => Return) => Curried<Parameters, Return>; /** * Returns the result of piping `value` through the given functions. * * @example * ```js playground * import { map, pipe, reduce, toArray } from 'lfi' * * console.log( * pipe( * [`sloth`, `lazy`, `sleep`], * map(word => word.toUpperCase()), * reduce(toArray()), * // Also works with non-`lfi` functions! * array => array.sort(), * ), * ) * //=> [ 'SLOTH', 'LAZY', 'SLEEP' ] * ``` * * @category Core * @since v0.0.1 */ declare const pipe: { <Value>(value: Value): Value; <A, B>(value: A, fn: (a: A) => B): B; <A, B, C>(value: A, fn1: (a: A) => B, fn2: (b: B) => C): C; <A, B, C, D>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): D; <A, B, C, D, E>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E): E; <A, B, C, D, E, F>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F): F; <A, B, C, D, E, F, G>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G): G; <A, B, C, D, E, F, G, H>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H): H; <A, B, C, D, E, F, G, H, I>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H, fn8: (h: H) => I): I; <A, B, C, D, E, F, G, H, I, J>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H, fn8: (h: H) => I, fn9: (i: I) => J): J; (value: unknown, ...fns: ((value: unknown) => unknown)[]): unknown; }; /** * Returns a function that takes a single parameter and pipes it through the * given functions. * * @example * ```js playground * import { compose, map, reduce, toArray } from 'lfi' * * const screamify = compose( * map(word => word.toUpperCase()), * reduce(toArray()), * // Also works with non-`lfi` functions! * array => array.sort(), * ) * * console.log(screamify([`sloth`, `lazy`, `sleep`])) * //=> [ 'SLOTH', 'LAZY', 'SLEEP' ] * ``` * * @category Core * @since v0.0.2 */ declare const compose: { (): <Value>(value: Value) => Value; <A, B>(fn: (a: A) => B): (value: A) => B; <A, B, C>(fn1: (a: A) => B, fn2: (b: B) => C): (value: A) => C; <A, B, C, D>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): (value: A) => D; <A, B, C, D, E>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E): (value: A) => E; <A, B, C, D, E, F>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F): (value: A) => F; <A, B, C, D, E, F, G>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G): (value: A) => G; <A, B, C, D, E, F, G, H>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H): (value: A) => H; <A, B, C, D, E, F, G, H, I>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H, fn8: (h: H) => I): (value: A) => I; <A, B, C, D, E, F, G, H, I, J>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G, fn7: (g: G) => H, fn8: (h: H) => I, fn9: (i: I) => J): (value: A) => J; (...fns: ((value: unknown) => unknown)[]): (value: unknown) => unknown; }; /** * Returns an async iterable wrapper around `iterable`. * * WARNING: When passing a concur iterable the default behavior of the returned * async iterable is to buffer the values yielded by the concur iterable if they * are not read from the async iterable as quickly as they are yielded by the * concur iterable. This happens because * [concur iterables are push-based while async iterables are pull-based](https://lfi.dev/docs/concepts/concurrent-iterable#how-is-it-different-from-an-asynciterable), * which creates backpressure. To customize how backpressure is applied, pass a * {@link BackpressureStrategy}. * * @example * ```js playground * import { asAsync } from 'lfi' * * const asyncIterable = asAsync([`sloth`, `lazy`, `sleep`]) * * console.log(typeof asyncIterable[Symbol.asyncIterator]) * //=> function * * for await (const value of asyncIterable) { * console.log(value) * } * //=> sloth * //=> lazy * //=> sleep * ``` * * @category Core * @since v0.0.2 */ declare const asAsync: { <Value>(iterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>): AsyncIterable<Awaited<Value>>; <Value, Size extends number = number>(concurIterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>, options?: AsAsyncOptions<Size>): AsyncIterable<Awaited<Value>>; }; /** * Options for {@link asAsync}. * * @category Core * @since v5.0.0 */ type AsAsyncOptions<Size extends number = number> = Readonly<{ /** * The strategy to use for applying backpressure when the input concur * iterable is yielding values faster than the returned async iterable can * process them. * * Does nothing if the input is not a concur iterable. * * @since v2.0.0 */ backpressureStrategy?: BackpressureStrategy<Size>; }>; /** * A strategy to use for applying backpressure adapting a concur iterable from * push-based iteration to pull-based iteration. * * @category Core * @since v5.0.0 */ type BackpressureStrategy<Size extends number = number> = Readonly<{ /** * The maximum number of values to buffer when the concur iterable yields * values faster than the downstream consumer can process them. * * Defaults to `Infinity`. */ bufferLimit?: PositiveInteger<Size>; /** * The strategy to apply when the {@link BackpressureStrategy.bufferLimit} * would be exceeded. * * The strategies behave as follows: * - `drop-first`: When the buffer is full, earlier buffered values are * evicted to make room for new ones. * - `drop-last`: When the buffer is full, new values are ignored. * - `error`: When the buffer is full and a new value comes in, an error is * thrown. * * Defaults to `error`. Note that `overflowStrategy` does nothing when * {@link BackpressureStrategy.bufferLimit} is `Infinity`. */ overflowStrategy?: `drop-first` | `drop-last` | `error`; }>; /** * A symbol used as the key when storing a {@link ConcurIterable}'s iteration * function. * * @category Core * @since v5.0.0 */ declare const concurIteratorSymbol: unique symbol; /** * Represents a lazy collection of values, each of type `Value`, that can be * iterated concurrently. * * The collection can be iterated by invoking the concur iterable's * {@link concurIteratorSymbol} function with an `apply` callback. The callback * is applied to each value in the collection, potentially asynchronously, in * some order. * * Invoking the concur iterable's {@link concurIteratorSymbol} function returns * a promise that resolves when `apply` has been applied to each value in the * concur iterable and each result returned by `apply` is awaited. * * A [concur iterable](https://lfi.dev/docs/concepts/concurrent-iterable) is * effectively a cold push-based observable backed by some asynchronous * operations. * * @example * ```js playground * import { asConcur, concurIteratorSymbol, mapConcur, pipe } from 'lfi' * * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en` * * const concurIterable = pipe( * asConcur([`sloth`, `lazy`, `sleep`]), * mapConcur(async word => { * const response = await fetch(`${API_URL}/${word}`) * return (await response.json())[0].phonetic * }), * ) * * await concurIterable[concurIteratorSymbol](console.log) * // NOTE: This order may change between runs * //=> /slɑθ/ * //=> /ˈleɪzi/ * //=> /sliːp/ * ``` * * @category Core * @since v0.0.2 */ type ConcurIterable<Value> = { [concurIteratorSymbol]: (apply: ConcurIterableApply<Value>) => Promise<void>; }; /** * The callback invoked for each value of a {@link ConcurIterable}. * * @category Core * @since v2.0.0 */ type ConcurIterableApply<Value> = (value: Value) => MaybePromiseLike<void>; /** * Returns a concur iterable wrapper around `iterable`. * * @example * ```js playground * import { asConcur, forEachConcur } from 'lfi' * * const concurIterable = asConcur([`sloth`, `lazy`, `sleep`]) * * await forEachConcur(console.log, concurIterable) * //=> sloth * //=> lazy * //=> sleep * ``` * * @category Core * @since v0.0.2 */ declare const asConcur: <Value>(iterable: Iterable<Value> | AsyncIterable<Value> | ConcurIterable<Value>) => ConcurIterable<Awaited<Value>>; /** * An iterable that contains zero values. * * Can be used as an iterable of any type. * * Like `[]`, but opaque. * * @example * ```js playground * import { empty } from 'lfi' * * console.log([...empty()]) * //=> [] * ``` * * @category Core * @since v0.0.1 */ declare const empty: <Value = unknown>() => Iterable<Value>; /** * An async iterable that contains zero values. * * Can be used as an async iterable of any type. * * Like `[]`, but for async iterables. * * @example * ```js playground * import { emptyAsync, pipe, reduceAsync, toArray } from 'lfi' * * console.log( * await pipe( * emptyAsync(), * reduceAsync(toArray()), * ), * ) * //=> [] * ``` * * @category Core * @since v0.0.1 */ declare const emptyAsync: <Value = unknown>() => AsyncIterable<Value>; /** * A concur iterable that contains zero values. * * Can be used as a concur iterable of any type. * * Like `[]`, but for concur iterables. * * @example * ```js playground * import { emptyConcur, pipe, reduceConcur, toArray } from 'lfi' * * console.log( * await pipe( * emptyConcur(), * reduceConcur(toArray()), * ), * ) * //=> [] * ``` * * @category Core * @since v0.0.2 */ declare const emptyConcur: <Value = unknown>() => ConcurIterable<Value>; /** * Returns an iterable equivalent, but not referentially equal, to `iterable`. * * @example * ```js playground * import { opaque } from 'lfi' * * const array = [`sloth`, `lazy`, `sleep`] * const iterable = opaque(array) * * console.log(array === iterable) * //=> false * * console.log([...iterable]) * //=> [ 'sloth', 'lazy', 'sleep' ] * ``` * * @category Core * @since v2.0.0 */ declare const opaque: <Value>(iterable: Iterable<Value>) => Iterable<Value>; /** * Returns an async iterable equivalent, but not referentially equal, to * `asyncIterable`. * * @example * ```js playground * import { asAsync, opaqueAsync, pipe, reduceAsync, toArray } from 'lfi' * * const asyncIterable = asAsync([`sloth`, `lazy`, `sleep`]) * asyncIterable.property = 42 * const opaqueAsyncIterable = opaqueAsync(asyncIterable) * * console.log(asyncIterable === opaqueAsyncIterable) * //=> false * * console.log(opaqueAsyncIterable.property) * //=> undefined * * console.log( * await pipe( * opaqueAsyncIterable, * reduceAsync(toArray()), * ), * ) * //=> [ 'sloth', 'lazy', 'sleep' ] * ``` * * @category Core * @since v2.0.0 */ declare const opaqueAsync: <Value>(asyncIterable: AsyncIterable<Value>) => AsyncIterable<Value>; /** * Returns an concur iterable equivalent, but not referentially equal, to * `concurIterable`. * * @example * ```js playground * import { asConcur, opaqueConcur, pipe, reduceConcur, toArray } from 'lfi' * * const concurIterable = asConcur([`sloth`, `lazy`, `sleep`]) * concurIterable.property = 42 * const opaqueConcurIterable = opaqueConcur(concurIterable) * * console.log(concurIterable === opaqueConcurIterable) * //=> false * * console.log(opaqueConcurIterable.property) * //=> undefined * * console.log( * await pipe( * opaqueConcurIterable, * reduceConcur(toArray()), * ), * ) * //=> [ 'sloth', 'lazy', 'sleep' ] * ``` * * @category Core * @since v2.0.0 */ declare const opaqueConcur: <Value>(concurIterable: ConcurIterable<Value>) => ConcurIterable<Value>; //#endregion //#region src/operations/optionals.d.ts /** * An iterable containing exactly zero or one values. * * @category Optionals * @since v2.0.0 */ type Optional<Value> = Iterable<Value>; /** * An async iterable containing exactly zero or one values. * * @category Optionals * @since v2.0.0 */ type AsyncOptional<Value> = AsyncIterable<Value>; /** * A concur iterable containing exactly zero or one values. * * @category Optionals * @since v2.0.0 */ type ConcurOptional<Value> = ConcurIterable<Value>; /** * Returns the only value in `iterable` if it contains exactly one value. * Otherwise, returns the result of invoking `fn`. * * @example * ```js playground * import { or, pipe } from 'lfi' * * console.log( * pipe( * [`sloth`], * or(() => `never called`), * ), * ) * //=> sloth * * console.log( * pipe( * [], * or(() => `called!`), * ), * ) * //=> called! * * console.log( * pipe( * [`sloth`, `lazy`, `sleep`], * or(() => `called!`), * ), * ) * //=> called! * ``` * * @category Optionals * @since v0.0.1 */ declare const or: { <Value>(fn: () => Value): (iterable: Iterable<Value>) => Value; <Value>(fn: () => Value, iterable: Iterable<Value>): Value; }; /** * Returns a promise that resolves to the only value in `asyncIterable` if it * contains exactly one value. Otherwise, returns a promise that resolves to * the awaited result of invoking `fn`. * * @example * ```js playground * import { asAsync, findAsync, orAsync, pipe } from 'lfi' * * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en` * * const findWordWithPartOfSpeech = partOfSpeech => * pipe( * asAsync([`sloth`, `lazy`, `sleep`]), * findAsync(async word => { * const response = await fetch(`${API_URL}/${word}`) * const [{ meanings }] = await response.json() * return meanings.some(meaning => meaning.partOfSpeech === partOfSpeech) * }), * orAsync(() => `no ${partOfSpeech}???`), * ) * * console.log(await findWordWithPartOfSpeech(`noun`)) * //=> sloth * console.log(await findWordWithPartOfSpeech(`verb`)) * //=> sloth * console.log(await findWordWithPartOfSpeech(`adjective`)) * //=> lazy * console.log(await findWordWithPartOfSpeech(`adverb`)) * //=> no adverb??? * ``` * * @category Optionals * @since v0.0.1 */ declare const orAsync: { <Value>(fn: () => MaybePromiseLike<Value>): (asyncIterable: AsyncIterable<Value>) => Promise<Value>; <Value>(fn: () => MaybePromiseLike<Value>, asyncIterable: AsyncIterable<Value>): Promise<Value>; }; /** * Returns a promise that resolves to the only value in `concurIterable` if it * contains exactly one value. Otherwise, returns a promise that resolves to * the awaited result of invoking `fn`. * * The promise only rejects if `fn` throws or rejects. It does not reject if the * given `concurIterable` rejects. Instead this function excludes erroring * values when counting the number of values in `concurIterable`. * * @example * ```js playground * import { asConcur, findConcur, orConcur, pipe } from 'lfi' * * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en` * * const findWordWithPartOfSpeech = partOfSpeech => * pipe( * asConcur([`sloth`, `lazy`, `sleep`]), * findConcur(async word => { * const response = await fetch(`${API_URL}/${word}`) * const [{ meanings }] = await response.json() * return meanings.some(meaning => meaning.partOfSpeech === partOfSpeech) * }), * orConcur(() => `no ${partOfSpeech}???`), * ) * * console.log(await findWordWithPartOfSpeech(`noun`)) * // NOTE: This word may change between runs * //=> sloth * console.log(await findWordWithPartOfSpeech(`verb`)) * // NOTE: This word may change between runs * //=> sloth * console.log(await findWordWithPartOfSpeech(`adjective`)) * //=> lazy * console.log(await findWordWithPartOfSpeech(`adverb`)) * //=> no adverb??? * ``` * * @category Optionals * @since v0.0.2 */ declare const orConcur: { <Value>(fn: () => MaybePromiseLike<Value>): (concurIterable: ConcurIterable<Value>) => Promise<Value>; <Value>(fn: () => MaybePromiseLike<Value>, concurIterable: ConcurIterable<Value>): Promise<Value>; }; /** * Returns the only value in `iterable` if it contains exactly one value. * Otherwise, throws an error. * * @example * ```js playground * import { get } from 'lfi' * * console.log(get([`sloth`])) * //=> sloth * * try { * console.log(get([])) * } catch { * console.log(`Oh no! It was empty...`) * } * //=> Oh no! It was empty... * * try { * console.log(get([`sloth`, `lazy`, `sleep`])) * } catch { * console.log(`Oh no! It had more than one value...`) * } * //=> Oh no! It had more than one value... * ``` * * @category Optionals * @since v0.0.1 */ declare const get: <Value>(iterable: Iterable<Value>) => Value; /** * Returns a promise that resolves to the only value in `asyncIterable` if it * contains exactly one value. Otherwise, returns a promise that rejects. * * @example * ```js playground * import { asAsync, findAsync, getAsync, pipe } from 'lfi' * * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en` * * const findWordWithPartOfSpeech = partOfSpeech => * pipe( * asAsync([`sloth`, `lazy`, `sleep`]), * findAsync(async word => { * const response = await fetch(`${API_URL}/${word}`) * const [{ meanings }] = await response.json() * return meanings.some(meaning => meaning.partOfSpeech === partOfSpeech) * }), * getAsync, * ) * * console.log(await findWordWithPartOfSpeech(`noun`)) * //=> sloth * console.log(await findWordWithPartOfSpeech(`verb`)) * //=> sloth * console.log(await findWordWithPartOfSpeech(`adjective`)) * //=> lazy * try { * console.log(await findWordWithPartOfSpeech(`adverb`)) * } catch { * console.log(`Oh no! It was empty...`) * } * //=> Oh no! It was empty... * ``` * * @category Optionals * @since v0.0.1 */ declare const getAsync: <Value>(asyncIterable: AsyncIterable<Value>) => Promise<Value>; /** * Returns a promise that resolves to the only value in `concurIterable` if it * contains exactly one value. Otherwise, returns a promise that rejects. * * The promise does not necessarily reject if the given `concurIterable` * rejects. Instead this function excludes erroring values when counting the * number of values in `concurIterable`. * * @example * ```js playground * import { asConcur, findConcur, getConcur, pipe } from 'lfi' * * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en` * * const findWordWithPartOfSpeech = partOfSpeech => * pipe( * asConcur([`sloth`, `lazy`, `sleep`]), * findConcur(async word => { * const response = await fetch(`${API_URL}/${word}`) * const [{ meanings }] = await response.json() * return meanings.some(meaning => meaning.partOfSpeech === partOfSpeech) * }), * getConcur, * ) * * console.log(await findWordWithPartOfSpeech(`noun`)) * // NOTE: This word may change between runs * //=> sloth * console.log(await findWordWithPartOfSpeech(`verb`)) * // NOTE: This word may change between runs * //=> sloth * console.log(await findWordWithPartOfSpeech(`adjective`)) * //=> lazy * try { * console.log(await findWordWithPartOfSpeech(`adverb`)) * } catch { * console.log(`Oh no! It was empty...`) * } * //=> Oh no! It was empty... * ``` * * @category Optionals * @since v0.0.2 */ declare const getConcur: <Value>(concurIterable: ConcurIterable<Value>) => Promise<Value>; /** * Returns a pair of iterables. If `iterable` is empty, then both of the * returned iterables are empty. Otherwise, the first iterable contains the * first value of `iterable` and the second iterable contains the rest of the * values of `iterable`. The second iterable can only be iterated once. * * @example * ```js playground * import { count, get, next } from 'lfi' * * const [first, rest] = next([`sloth`, `lazy`, `sleep`]) * * console.log(get(first)) * //=> sloth * * console.log([...rest]) * //=> [ 'lazy', 'sleep' ] * * const [first2, rest2] = next([]) * * console.log(count(first2)) * //=> 0 * * console.log(count(rest2)) * //=> 0 * ``` * * @category Optionals * @since v0.0.1 */ declare const next: <Value>(iterable: Iterable<Value>) => [Optional<Value>, Iterable<Value>]; /** * Returns a promise that resolves to a pair of async iterables. If * `asyncIterable` is empty, then both of the returned async iterables are * empty. Otherwise, the first async iterable contains the first value of * `asyncIterable` and the second async iterable contains the rest of the values * of `asyncIterable`. The second async iterable can only be iterated once. * * @example * ```js playground * import { asAsync, countAsync, emptyAsync, getAsync, mapAsync, nextAsync, pipe, reduceAsync, toArray } from 'lfi' * * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en` * * const [first, rest] = await pipe( * asAsync([`sloth`, `lazy`, `sleep`]), * mapAsync(async word => { * const response = await fetch(`${API_URL}/${word}`) * return (await response.json())[0].phonetic * }), * nextAsync, * ) * * console.log(await getAsync(first)) * //=> /slɑθ/ * * console.log( * await pipe( * rest, * reduceAsync(toArray()), * ), * ) * //=> [ '/ˈleɪzi/', '/sliːp/' ] * * const [first2, rest2] = await nextAsync(emptyAsync) * * console.log(await countAsync(first2)) * //=> 0 * * console.log(await countAsync(rest2)) * //=> 0 * ``` * * @category Optionals * @since v0.0.1 */ declare const nextAsync: <Value>(asyncIterable: AsyncIterable<Value>) => Promise<[AsyncOptional<Value>, AsyncIterable<Value>]>; //#endregion //#region src/operations/reducers.d.ts /** * A reducer that reduces by combining pairs of values using function * application. * * @example * ```js playground * import { or, pipe, reduce } from 'lfi' * * console.log( * pipe( * [1, 2, 3, 4], * reduce( * // This is a `FunctionReducer` * (number1, number2) => number1 + number2, * ), * or(() => 0), * ), * ) * //=> 10 * ``` * * @category Reducers * @since v2.0.0 */ type FunctionReducer<Value = unknown> = (acc: Value, value: Value) => Value; /** * A reducer that reduces by combining pairs of values using * {@link RawOptionalReducerWithoutFinish.add}. * * @example * ```js playground * import { or, pipe, reduce } from 'lfi' * * console.log( * pipe( * [1, 2, 3, 4], * reduce( * // This is a `RawOptionalReducerWithoutFinish` * { * add: (number1, number2) => number1 + number2, * }, * ), * or(() => 0), * ), * ) * //=> 10 * ``` * * @category Reducers * @since v2.0.0 */ type RawOptionalReducerWithoutFinish<Value = unknown, This = unknown> = { add: (this: This, acc: Value, value: Value) => Value; }; /** * A reducer that reduces by combining pairs of values using * {@link RawOptionalReducerWithoutFinish.add} and then transforming the final * value using {@link RawOptionalReducerWithFinish.finish}. * * @example * ```js playground * import { or, pipe, reduce } from 'lfi' * * console.log( * pipe( * [1, 2, 3, 4], * reduce( * // This is a `RawOptionalReducerWithFinish` * { * add: (number1, number2) => number1 + number2, * finish: sum => `The sum is ${sum}`, * }, * ), * or(() => `There are no numbers`), * ), * ) * //=> The sum is 10 * ``` * * @category Reducers * @since v2.0.0 */ type RawOptionalReducerWithFinish<Value = unknown, Finished = Value, This = unknown> = RawOptionalReducerWithoutFinish<Value, This> & { finish: (this: This, acc: Value) => Finished; }; /** * A reducer that reduces by combining pairs of values using * {@link RawOptionalReducerWithoutFinish.add} and then transforming the final * value using {@link RawOptionalReducerWithFinish.finish}. * * It's identical to {@link RawOptionalReducerWithFinish} except its `this` is * bound by {@link normalizeReducer}. * * @example * ```js playground * import { or, pipe, reduce } from 'lfi' * * console.log( * pipe( * [1, 2, 3, 4], * reduce( * // This will be an `OptionalReducer` once it's normalized by `reduce` * { * add: (number1, number2) => number1 + number2, * finish: sum => `The sum is ${sum}`, * }, * ), * or(() => `There are no numbers`), * ), * ) * //=> The sum is 10 * ``` * * @category Reducers * @since v2.0.0 */ type OptionalReducer<Value = unknown, Finished = Value> = RawOptionalReducerWithFinish<Value, Finished>; /** * A reducer that reduces by creating an initial accumulator using * {@link RawReducerWithoutFinish.create} and then adding values to the * accumulator values using {@link RawReducerWithoutFinish.add}. * * @example * ```js playground * import { pipe, reduce } from 'lfi' * * console.log( * pipe( * [1, 2, 3, 4], * reduce( * // This is a `RawReducerWithoutFinish` * { * create: () => 0, * add: (number1, number2) => number1 + number2, * }, * ), * ), * ) * //=> 10 * ``` * * @category Reducers * @since v2.0.0 */ type RawReducerWithoutFinish<Value = unknown, Acc = Value, This = unknown> = { create: (this: This) => Acc; add: (this: This, acc: Acc, value: Value) => Acc; }; /** * A reducer that reduces by creating an initial accumulator using * {@link RawReducerWithoutFinish.create}, then adding values to the accumulator * values using {@link RawReducerWithoutFinish.add}, and then transforming the * final accumulator using {@link RawReducerWithFinish.finish}. * * @example * ```js playground * import { pipe, reduce } from 'lfi' * * console.log( * pipe( * [1, 2, 3, 4], * reduce( * // This is a `RawReducerWithFinish` * { * create: () => 0, * add: (number1, number2) => number1 + number2, * finish: sum => `The sum is ${sum}`, * }, * ), * ), * ) * //=> The sum is 10 * ``` * * @category Reducers * @since v2.0.0 */ type RawReducerWithFinish<Value = unknown, Acc = Value, Finished = Acc, This = unknown> = RawReducerWithoutFinish<Value, Acc, This> & { finish: (this: This, acc: Acc) => Finished; }; /** * A reducer that reduces by creating an initial accumulator using * {@link RawReducerWithoutFinish.create}, then adding values to the accumulator * values using {@link RawReducerWithoutFinish.add}, and then transforming the * final accumulator using {@link RawReducerWithFinish.finish}. * * It's identical to {@link RawReducerWithFinish} except its `this` is bound by * {@link normalizeReducer}. * * @example * ```js playground * import { pipe, reduce } from 'lfi' * * console.log( * pipe( * [1, 2, 3, 4], * reduce( * // This will be a `Reducer` once it's normalized by `reduce` * { * create: () => 0, * add: (number1, number2) => number1 + number2, * finish: sum => `The sum is ${sum}`, * }, * ), * ), * ) * //=> The sum is 10 * ``` * * @category Reducers * @since v2.0.0 */ type Reducer<Value = unknown, Acc = Value, Finished = Acc> = RawReducerWithFinish<Value, Acc, Finished>; /** * A keyed reducer that reduces by creating an initial accumulator using * {@link RawReducerWithoutFinish.create} and then adding key-value pairs to the * accumulator values using {@link RawReducerWithoutFinish.add}. The accumulator can be * queried for values by key using {@link RawKeyedReducer.get}. * * @category Reducers * @since v2.0.0 */ type RawKeyedReducer<Key = unknown, Value = unknown, Acc = [Key, Value], This = unknown> = RawReducerWithoutFinish<readonly [Key, Value], Acc, This> & { get: (this: This, acc: Acc, key: Key) => Value | typeof NO_ENTRY; }; /** * A keyed reducer that reduces by creating an initial accumulator using * {@link RawReducerWithoutFinish.create} and then adding key-value pairs to the * accumulator values using {@link RawReducerWithoutFinish.add}. The accumulator * can be queried for values by key using {@link RawKeyedReducer.get}. * * @category Reducers * @since v2.0.0 */ type KeyedReducer<Key = unknown, Value = unknown, Acc = [Key, Value]> = RawKeyedReducer<Key, Value, Acc>; /** * An async reducer that reduces by combining pairs of values using function * application. * * @category Reducers * @since v2.0.0 */ type AsyncFunctionReducer<Value = unknown> = (acc: Value, value: Value) => MaybePromiseLike<Value>; /** * An async reducer that reduces by combining pairs of values using * {@link RawAsyncOptionalReducerWithoutFinish.add}. * * @category Reducers * @since v2.0.0 */ type RawAsyncOptionalReducerWithoutFinish<Value = unknown, This = unknown> = { add: (this: This, acc: Value, value: Value) => MaybePromiseLike<Value>; }; /** * An async reducer that reduces by combining pairs of values using * {@link RawAsyncOptionalReducerWithoutFinish.add} and then transforming the * final value using {@link RawAsyncOptionalReducerWithFinish.finish}. * * @category Reducers * @since v2.0.0 */ type RawAsyncOptionalReducerWithFinish<Value = unknown, Finished = Value, This = unknown> = RawAsyncOptionalReducerWithoutFinish<Value, This> & { finish: (this: This, acc: Value) => MaybePromiseLike<Finished>; }; /** * An async reducer that reduces by combining pairs of values using * {@link RawAsyncOptionalReducerWithoutFinish.add} and then transforming the * final value using {@link RawAsyncOptionalReducerWithFinish.finish}. * * @category Reducers * @since v2.0.0 */ type AsyncOptionalReducer<Value = unknown, Finished = Value> = RawAsyncOptionalReducerWithFinish<Value, Finished>; /** * An async reducer that reduces by creating an initial accumulator using * {@link RawAsyncReducerWithoutFinish.create} and then adding values to the * accumulator values using {@link RawAsyncReducerWithoutFinish.add}. The async * reducer is optionally able to combine pairs of accumulators using * {@link RawAsyncReducerWithoutFinish.combine}. * * @category Reducers * @since v2.0.0 */ type RawAsyncReducerWithoutFinish<Value = unknown, Acc = Value, This = unknown> = { create: (this: This) => MaybePromiseLike<Acc>; add: (this: This, acc: Acc, value: Value) => MaybePromiseLike<Acc>; combine?: (this: This, acc1: Acc, acc2: Acc) => MaybePromiseLike<Acc>; }; /** * An async reducer that reduces by creating an initial accumulator using * {@link RawAsyncReducerWithoutFinish.create}, then adding values to the * accumulator values using {@link RawAsyncReducerWithoutFinish.add}, and then * transforming the final accumulator using * {@link RawAsyncReducerWithFinish.finish}. The async * reducer is optionally able to combine pairs of accumulators using * {@link RawAsyncReducerWithoutFinish.combine}. * * @category Reducers * @since v2.0.0 */ type RawAsyncReducerWithFinish<Value = unknown, Acc = Value, Finished = Acc, This = unknown> = RawAsyncReducerWithoutFinish<Value, Acc, This> & { finish: (this: This, acc: Acc) => MaybePromiseLike<Finished>; }; /** * An async reducer that reduces by creating an initial accumulator using * {@link RawAsyncReducerWithoutFinish.create}, then adding values to the * accumulator values using {@link RawAsyncReducerWithoutFinish.add}, and then * transforming the final accumulator using * {@link RawAsyncReducerWithFinish.finish}. The async reducer is optionally * able to combine pairs of accumulators using * {@link RawAsyncReducerWithoutFinish.combine}. * * @category Reducers * @since v2.0.0 */ type AsyncReducer<Value = unknown, Acc = Value, Finished = Acc> = RawAsyncReducerWithFinish<Value, Acc, Finished>; /** * An async keyed reducer that reduces by creating an initial accumulator using * {@link RawAsyncReducerWithoutFinish.create} and then adding key-value pairs * to the accumulator values using {@link RawAsyncReducerWithoutFinish.add}. The * async keyed reducer is optionally able to combine pairs of accumulators using * {@link RawAsyncReducerWithoutFinish.combine}. The accumulator can be queried * for values by key using {@link RawAsyncKeyedReducer.get}. * * @category Reducers * @since v2.0.0 */ type RawAsyncKeyedReducer<Key = unknown, Value = unknown, Acc = [Key, Value], This = unknown> = RawAsyncReducerWithoutFinish<readonly [Key, Value], Acc, This> & { get: (this: This, acc: Acc, key: Key) => MaybePromiseLike<Value | typeof NO_ENTRY>; }; /** * An async keyed reducer that reduces by creating an initial accumulator using * {@link RawAsyncReducerWithoutFinish.create} and then adding key-value pairs * to the accumulator values using {@link RawAsyncReducerWithoutFinish.add}. The * async keyed reducer is optionally able to combine pairs of accumulators using * {@link RawAsyncReducerWithoutFinish.combine}. The accumulator can be queried * for values by key using {@link RawAsyncKeyedReducer.get}. * * @category Reducers * @since v2.0.0 */ type AsyncKeyedReducer<Key = unknown, Value = unknown, Acc = [Key, Value]> = RawAsyncKeyedReducer<Key, Value, Acc>; /** * A unique value representing the lack of an entry for some key in a * {@link KeyedReducer} or {@link AsyncKeyedReducer}. * * Keyed reducers use this instead of `null` or `undefined` because they are * valid values. Furthermore, introducing a `has` method for the purpose of * disambiguation would be less performant due to the need to perform the lookup * twice when the entry exists: `has` followed by `get` for the same key. * * @category Reducers * @since v2.0.0 */ declare const NO_ENTRY: unique symbol; /** * Returns a {@link Reducer} or {@link OptionalReducer} equivalent to `reducer` * except its final value is transformed using `fn`. * * @category Reducers * @since v2.0.0 */ declare const mapReducer: { <Value, Acc, From, To, This>(fn: (value: From) => To, reducer: Readonly<RawReducerWithFinish<Value, Acc, From, This>>): Reducer<Value, Acc, To>; <From, To>(fn: (value: From) => To): <Value, Acc, This>(reducer: Readonly<RawReducerWithFinish<Value, Acc, From, This>>) => Reducer<Value, Acc, To>; <Value, From, To, This>(fn: (value: From) => To, reducer: Readonly<RawReducerWithoutFinish<Value, From, This>>): Reducer<Value, To>; <From, To>(fn: (value: From) => To): <Value, This>(reducer: Readonly<RawReducerWithoutFinish<Value, From, This>>) => Reducer<Value, To>; <Value, From, To, This>(fn: (value: From) => To, reducer: Readonly<RawOptionalReducerWithFinish<Value, From, This>>): OptionalReducer<Value, To>; <From, To>(fn: (value: From) => To): <Value, This>(reducer: Readonly<RawOptionalReducerWithFinish<Value, From, This>>) => OptionalReducer<Value, To>; <From, To, This>(fn: (value: From) => To, reducer: Readonly<RawOptionalReducerWithoutFinish<From, This>>): OptionalReducer<To>; <From, To>(fn: (value: From) => To): <This>(reducer: Readonly<RawOptionalReducerWithoutFinish<From, This>>) => OptionalReducer<To>; <From, To>(fn: (value: From) => To, reducer: FunctionReducer<From>): OptionalReducer<To>; <From, To>(fn: (value: From) => To): (reducer: FunctionReducer<From>) => OptionalReducer<To>; }; /** * Returns an {@link AsyncReducer} equivalent to `reducer` except its final * value is transformed using `fn`. * * @category Reducers * @since v2.0.0 */ declare const mapAsyncReducer: { <Value, Acc, From, To, This>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, From, This>>): AsyncReducer<Value, Acc, To>; <From, To>(fn: (value: From) => MaybePromiseLike<To>): <Value, Acc, This>(asyncReducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, From, This>>) => AsyncReducer<Value, Acc, To>; <Value, From, To, This>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: Readonly<RawAsyncReducerWithoutFinish<Value, From, This>>): AsyncReducer<Value, To>; <From, To>(fn: (value: From) => MaybePromiseLike<To>): <Value, This>(asyncReducer: Readonly<RawAsyncReducerWithoutFinish<Value, From, This>>) => AsyncReducer<Value, To>; <Value, From, To, This>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: Readonly<RawAsyncOptionalReducerWithFinish<Value, From, This>>): AsyncOptionalReducer<Value, To>; <From, To>(fn: (value: From) => MaybePromiseLike<To>): <Value, This>(asyncReducer: Readonly<RawAsyncOptionalReducerWithFinish<Value, From, This>>) => AsyncOptionalReducer<Value, To>; <From, To, This>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: Readonly<RawAsyncOptionalReducerWithoutFinish<From, This>>): AsyncOptionalReducer<To>; <From, To>(fn: (value: From) => MaybePromiseLike<To>): <This>(asyncReducer: Readonly<RawAsyncOptionalReducerWithoutFinish<From, This>>) => AsyncOptionalReducer<To>; <From, To>(fn: (value: From) => MaybePromiseLike<To>, asyncReducer: AsyncFunctionReducer<From>): AsyncOptionalReducer<To>; <From, To>(fn: (value: From) => MaybePromiseLike<To>): (asyncReducer: AsyncFunctionReducer<From>) => AsyncOptionalReducer<To>; }; /** * Returns a non-raw version of `reducer`. * * @category Reducers * @since v2.0.0 */ declare const normalizeReducer: { <Key, Value, Acc, This>(reducer: Readonly<RawKeyedReducer<Key, Value, Acc, This>>): KeyedReducer<Key, Value, Acc>; <Value, Acc, Finished, This>(reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>): Reducer<Value, Acc, Finished>; <Value, Acc, This>(reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>): Reducer<Value, Acc>; <Value, Finished, This>(reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>): OptionalReducer<Value, Finished>; <Value, This>(reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>): OptionalReducer<Value>; <Value>(reducer: FunctionReducer<Value>): OptionalReducer<Value>; <Key, Value, Acc, This>(reducer: Readonly<RawAsyncKeyedReducer<Key, Value, Acc, This>>): AsyncKeyedReducer<Key, Value, Acc>; <Value, Acc, Finished, This>(reducer: Readonly<RawAsyncReducerWithFinish<Value, Acc, Finished, This>>): AsyncReducer<Value, Acc, Finished>; <Value, Acc, This>(reducer: Readonly<RawAsyncReducerWithoutFinish<Value, Acc, This>>): AsyncReducer<Value, Acc>; <Value, Finished, This>(reducer: Readonly<RawAsyncOptionalReducerWithFinish<Value, Finished, This>>): AsyncOptionalReducer<Value, Finished>; <Value, This>(reducer: Readonly<RawAsyncOptionalReducerWithoutFinish<Value, This>>): AsyncOptionalReducer<Value>; <Value>(reducer: AsyncFunctionReducer<Value>): AsyncOptionalReducer<Value>; }; /** * Returns the result of reducing `iterable` using `reducer`. * * An initial accumulator is created using * {@link RawReducerWithoutFinish.create}. Then each value in `iterable` is * added to the accumulator and the current accumulator is updated using * {@link RawReducerWithoutFinish.add}. Finally, the resulting accumulator is * transformed using {@link RawReducerWithFinish.finish} if specified. * * If `reducer` is an optional reducer (no * {@link RawReducerWithoutFinish.create} method), then an empty iterable is * returned if `iterable` is empty. Otherwise, an iterable containing the result * of reducing using the first value of the iterable as the initial accumulator * is returned. * * Like `Array.prototype.reduce`, but for iterables. * * @example * ```js playground * console.log( * pipe( * [`sloth`, `more sloth`, `even more sloth`], * map(string => string.length), * reduce(toArray()), * ), * ) * //=> [ 5, 10, 15 ] * ``` * * @category Reducers * @since v0.0.1 */ declare const reduce: { <Value, Acc, Finished, This>(reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>, iterable: Iterable<Value>): Finished; <Value, Acc, Finished, This>(reducer: Readonly<RawReducerWithFinish<Value, Acc, Finished, This>>): (iterable: Iterable<Value>) => Finished; <Value, Acc, This>(reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>, iterable: Iterable<Value>): Acc; <Value, Acc, This>(reducer: Readonly<RawReducerWithoutFinish<Value, Acc, This>>): (iterable: Iterable<Value>) => Acc; <Value, Finished, This>(reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>, iterable: Iterable<Value>): Optional<Finished>; <Value, Finished, This>(reducer: Readonly<RawOptionalReducerWithFinish<Value, Finished, This>>): (iterable: Iterable<Value>) => Optional<Finished>; <Value, This>(reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>, iterable: Iterable<Value>): Optional<Value>; <Value, This>(reducer: Readonly<RawOptionalReducerWithoutFinish<Value, This>>): (iterable: Iterable<Value>) => Optional<Value>; <Value>(reducer: FunctionReducer<Value>, iterable: Iterable<Value>): Optional<Value>; <Value>(reducer: FunctionReducer<Value>): (iterable: Iterable<Value>) => Optional<Value>; }; /** * Returns the result of reducing the `asyncIterable` using `asyncReducer`. * * Informally, an initial accumulator is created using * {@link RawAsyncReducerWithoutFinish.create}. Then each value in * `asyncIterable` is added to the accumulator and the current accumulator is * updated using {@link RawAsyncReducerWithoutFinish.add}. Finally, the * resulting accumulator is transformed using * {@link RawAsyncReducerWithFinish.finish} if specified. Multiple accumulators * may be created, added to, and then combined if supported via * {@link RawAsyncReducerWithoutFinish.combine} and the next value of * `asyncIterable` is ready before promises from * {@link RawAsyncReducerWithoutFinish.add} resolve. * * If `asyncReducer` is an async optional reducer (no * {@link RawAsyncReducerWithoutFinish.create} method), then an empty async * iterable is returned if `asyncIterable` is empty. Otherwise, an async * iterable containing the result of reducing using the first value of the async * iterable as the initial accumulator is returned. * * Like `Array.prototype.reduce`, but for async iterables. * * @example * ```js playground * import { asAsync, mapAsync, pipe, reduceAsync, toArray } from 'lfi' * * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en` * * console.log( * await pipe( * asAsync([`sloth`, `lazy`, `sleep`]), * mapAsync(async word => { * const response = await fetch(`${API_URL}/${word}`) * return (await response.json())[0].phonetic * }), * reduceAsync(toArray()), * ), * ) * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ] * ``` * * @category Reducers * @since v0.0.1 */ declare const reduceAsync: { <Value, Acc, Finished, This>(asyncReducer: RawAsyncReducerWithFinish<Value, Acc, Finished, This> | RawReducerWithFinish<Value, Acc, Finished, This>, asyncIterable: AsyncIterable<Value>): Promise<Finished>; <Value, Acc, Finished, This>(asyncReducer: RawAsyncReducerWithFinish<Value, Acc, Finished, This> | RawReducerWithFinish<Value, Acc, Finished, This>): (asyncIterable: AsyncIterable<Value>) => Promise<Finished>; <Value, Acc, This>(asyncReducer: RawAsyncReducerWithoutFinish<Value, Acc, This> | RawReducerWithoutFinish<Value, Acc, This>, asyncIterable: AsyncIterable<Value>): Promise<Acc>; <Value, Acc, This>(asyncReducer: RawAsyncReducerWithoutFinish<Value, Acc, This> | RawReducerWithoutFinish<Value, Acc, This>): (asyncIterable: AsyncIterable<Value>) => Promise<Acc>; <Value, Finished, This>(asyncReducer: RawAsyncOptionalReducerWithFinish<Value, Finished, This> | RawOptionalReducerWithFinish<Value, Finished, This>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Finished>; <Value, Finished, This>(asyncReducer: RawAsyncOptionalReducerWithFinish<Value, Finished, This> | RawOptionalReducerWithFinish<Value, Finished, This>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Finished>; <Value, This>(asyncReducer: RawAsyncOptionalReducerWithoutFinish<Value, This> | RawOptionalReducerWithoutFinish<Value, This>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Value>; <Value, This>(asyncReducer: RawAsyncOptionalReducerWithoutFinish<Value, This> | RawOptionalReducerWithoutFinish<Value, This>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>; <Value>(asyncReducer: AsyncFunctionReducer<Value> | FunctionReducer<Value>, asyncIterable: AsyncIterable<Value>): AsyncOptional<Value>; <Value>(asyncReducer: AsyncFunctionReducer<Value> | FunctionReducer<Value>): (asyncIterable: AsyncIterable<Value>) => AsyncOptional<Value>; }; /** * Returns the result of reducing the `concurIterable` using `asyncReducer`. * * The resulting promise or concur iterable rejects if `concurIterable` rejects. * * Informally, an initial accumulator is created using * {@link RawAsyncReducerWithoutFinish.create}. Then each value in * `concurIterable` is added to the accumulator and the current accumulator is * updated using {@link RawAsyncReducerWithoutFinish.add}. Finally, the * resulting accumulator is transformed using * {@link RawAsyncReducerWithFinish.finish} if specified. Multiple accumulators * may be created, added to, and then combined if supported via * {@link RawAsyncReducerWithoutFinish.combine} and the next value of * `concurIterable` is ready before promises from * {@link RawAsyncReducerWithoutFinish.add} resolve. * * If `asyncReducer` is an async optional reducer (no * {@link RawAsyncReducerWithoutFinish.create} method), then an empty concur * iterable is returned if `concurIterable` is empty. Otherwise, an concur * iterable containing the result of reducing using the first value of the * concur iterable as the initial accumulator is returned. * * Like `Array.prototype.reduce`, but for concur iterables. * * @example * ```js playground * import { asConcur, mapConcur, pipe, reduceConcur, toArray } from 'lfi' * * const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en` * * console.log( * await pipe( * asConcur([`sloth`, `lazy`, `sleep`]), * mapConcur(async word => { * const response = await fetch(`${API_URL}/${word}`) * return (await response.json())[0].phonetic * }), * reduceConcur(toArray()), * ), * ) * // NOTE: This order may change between runs * //=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ] * ``` * * @category Reducers * @since v0.0.1 */ declare const reduceConcur: { <Value, Acc, Finished, This>(asyncReducer: RawAsyncReducerWithFinish<Value, Acc, Finished, This> | RawReducerWithFinish<Value, Acc, Finished, This>, concurIterable: ConcurIterable<Value>): Promise<Finished>; <Value, Acc, Finished, This>(asyncReducer: RawAsyncReducerWithFinish<Value, Acc, Finished, This> | RawReducerWithFinish<Value, Acc, Finished, This>): (concurIterable: ConcurIterable<Value>) => Promise<Finished>; <Value, Acc, This>(asyncReducer: RawAsyncReducerWithoutFinish<Value, Acc, This> | RawReducerWithoutFinish<Value, Acc, This>, concurIterable: ConcurIterable<Value>): Promise<Acc>; <Value, Acc, This>(asyncReducer: RawAsyncReducerWithoutFinish<Value, Acc, This> | RawReducerWithoutFinish<Value, Acc, This>): (concurIterable: ConcurIterable<Value>) => Promise<Acc>; <Value, Finished, This>(asyncRe