lfi
Version:
A lazy functional iteration library supporting sync, async, and concurrent iteration.
1,405 lines (1,345 loc) • 207 kB
TypeScript
//#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