Skip to main content

API

Collections

FunctionDescription

join

Returns the string concatenation of the values of iterable, separated by separator.

Like Array.prototype.join, but for iterables, except it does not treat null, undefined, or [] specially.

Example

import { join, map, pipe } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
map(word => word.toUpperCase()),
join(`, `),
),
)
//=> SLOTH, LAZY, SLEEP
Playground

Since

v0.0.1

joinAsync

Returns a promise that resolves to the string concatenation of the values of asyncIterable, separated by separator.

Like Array.prototype.join, but for async iterables, except it does not treat null, undefined, or [] specially.

Example

import { asAsync, joinAsync, mapAsync, pipe } 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
}),
joinAsync(`, `),
),
)
//=> /slɑθ/, /ˈleɪzi/, /sliːp/
Playground

Since

v0.0.1

joinConcur

Returns a promise that resolves to the string concatenation of the values of concurIterable, separated by separator.

Like Array.prototype.join, but for concur iterables, except it does not treat null, undefined, or [] specially.

WARNING: The iteration order of concur iterables is not deterministic, so the values will be concatenated in an arbitrary order.

Example

import { asConcur, joinConcur, mapConcur, pipe } 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
}),
joinConcur(`, `),
),
)
// NOTE: This order may change between runs
//=> /slɑθ/, /ˈleɪzi/, /sliːp/
Playground

Since

v0.0.2

toArray

Returns a Reducer that collects values to an Array.

Example

import { cycle, pipe, reduce, take, toArray } from 'lfi'

console.log(
pipe(
cycle([`sloth`, `lazy`, `sleep`]),
take(4),
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy', 'sleep', 'sloth' ]
Playground

Since

v0.0.1

toGrouped

Returns a Reducer that reduces key-value pairs using outerReducer and reduces values with the same key using innerReducer.

Example

import { map, pipe, reduce, toArray, toGrouped, toMap } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
map(word => [word.length, word]),
reduce(toGrouped(toArray(), toMap())),
),
)
//=> Map(2) {
//=> 5 => [ 'sloth', 'sleep' ],
//=> 4 => [ 'lazy' ]
//=> }
Playground

Since

v2.0.0

toJoin

Returns a Reducer that concatenates values to a string where values are separated by separator.

Joins like Array.prototype.join, but does not treat null, undefined, or [] specially.

Use when composing reducers. Prefer join, joinAsync, and joinConcur for direct use on iterables.

Example

import { map, pipe, reduce, toGrouped, toJoin, toMap } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
map(word => [word.length, word]),
reduce(toGrouped(toJoin(`,`), toMap())),
),
)
//=> Map(2) {
//=> 5 => 'sloth,sleep',
//=> 4 => 'lazy'
//=> }
Playground

Since

v2.0.0

toMap

Returns a KeyedReducer that collects key-value pairs to a Map.

In the case of pairs with duplicate keys, the value of the last one wins.

Example

import { map, pipe, reduce, toMap } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
map(word => [word, word.length]),
reduce(toMap()),
),
)
//=> Map(3) {
//=> 'sloth' => 5,
//=> 'lazy' => 4,
//=> 'sleep' => 5
//=> }
Playground

Since

v0.0.1

toMultiple

Returns a Reducer or OptionalReducer that reduces values to an object or array of the same shape as reducers using all of the reducers in reducers.

Returns an OptionalReducer if at least one of the input reducers is an OptionalReducer. Otherwise, returns a Reducer.

Example

import { map, pipe, reduce, toCount, toJoin, toMultiple, toSet } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
map(word => word.length),
reduce(toMultiple([toSet(), toCount(), toJoin(`,`)])),
),
)
//=> [
//=> Set(2) { 5, 4 },
//=> 3,
//=> '5,4,5'
//=> ]

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
map(word => word.length),
reduce(
toMultiple({
set: toSet(),
count: toCount(),
string: toJoin(`,`),
}),
),
),
)
//=> {
//=> set: Set(2) { 5, 4 },
//=> count: 3,
//=> string: '5,4,5'
//=> }
Playground

Since

v2.0.0

toObject

Returns a KeyedReducer that collects key-value pairs to an object.

In the case of pairs with duplicate keys, the value of the last one wins.

Example

import { map, pipe, reduce, toObject } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
map(word => [word, word.length]),
reduce(toObject()),
),
)
//=> {
//=> sloth: 5,
//=> lazy: 4,
//=> sleep: 5
//=> }
Playground

Since

v0.0.1

toSet

Returns a Reducer that collects values to a Set.

Example

import { cycle, pipe, reduce, take, toSet } from 'lfi'

console.log(
pipe(
cycle([`sloth`, `lazy`, `sleep`]),
take(4),
reduce(toSet()),
),
)
//=> Set(3) {
//=> 'sloth',
//=> 'lazy',
//=> 'sleep'
//=> }
Playground

Since

v0.0.1

toWeakMap

Returns a KeyedReducer that collects key-value pairs to a WeakMap.

In the case of pairs with duplicate keys, the value of the last one wins.

Example

import { map, pipe, reduce, toWeakMap } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
map(word => [{ sloth: word }, word.length]),
reduce(toWeakMap()),
),
)
//=> WeakMap { <items unknown> }
Playground

Since

v0.0.1

toWeakSet

Returns a Reducer that collects objects to a WeakSet.

Example

import { cycle, map, pipe, reduce, take, toWeakSet } from 'lfi'

console.log(
pipe(
cycle([`sloth`, `lazy`, `sleep`]),
take(4),
map(word => ({ sloth: word })),
reduce(toWeakSet()),
),
)
//=> WeakSet { <items unknown> }
Playground

Since

v0.0.1

Core

Type alias, Variable, FunctionDescription

ConcurIterable

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 with an apply callback. The callback is applied to each value in the collection, potentially asynchronously, in some order.

Invoking the concur iterable 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 is effectively a cold push-based observable backed by some asynchronous operations.

Example

import { asConcur, 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(console.log)
// NOTE: This order may change between runs
//=> /slɑθ/
//=> /ˈleɪzi/
//=> /sliːp/
Playground

Since

v0.0.2

ConcurIterableApply

The callback invoked for each value of a ConcurIterable.

Since

v2.0.0

empty

An iterable that contains zero values.

Can be used as an iterable of any type.

Like [], but opaque.

Example

import { empty } from 'lfi'

console.log([...empty])
//=> []
Playground

Since

v0.0.1

emptyAsync

An async iterable that contains zero values.

Can be used as an async iterable of any type.

Like [], but for async iterables.

Example

import { emptyAsync, pipe, reduceAsync, toArray } from 'lfi'

console.log(
await pipe(
emptyAsync,
reduceAsync(toArray()),
),
)
//=> []
Playground

Since

v0.0.1

asAsync

Returns an async iterable wrapper around iterable.

WARNING: When passing a concur iterable the returned async iterable will 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, which creates backpressure.

Example

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
Playground

Since

v0.0.2

asConcur

Returns a concur iterable wrapper around iterable.

Example

import { asConcur, forEachConcur } from 'lfi'

const concurIterable = asConcur([`sloth`, `lazy`, `sleep`])

await forEachConcur(console.log, concurIterable)
//=> sloth
//=> lazy
//=> sleep
Playground

Since

v0.0.2

compose

Returns a function that takes a single parameter and pipes it through the given functions.

Example

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' ]
Playground

Since

v0.0.2

curry

Returns a curried version of fn.

Example

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 !
Playground

Since

v0.0.1

emptyConcur

A concur iterable that contains zero values.

Can be used as a concur iterable of any type.

Like [], but for concur iterables.

Example

import { emptyConcur, pipe, reduceConcur, toArray } from 'lfi'

console.log(
await pipe(
emptyConcur,
reduceConcur(toArray()),
),
)
//=> []
Playground

Since

v0.0.2

opaque

Returns an iterable equivalent, but not referentially equal, to iterable.

Example

import { opaque } from 'lfi'

const array = [`sloth`, `lazy`, `sleep`]
const iterable = opaque(array)

console.log(array === iterable)
//=> false

console.log([...iterable])
//=> [ 'sloth', 'lazy', 'sleep' ]
Playground

Since

v2.0.0

opaqueAsync

Returns an async iterable equivalent, but not referentially equal, to asyncIterable.

Example

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' ]
Playground

Since

v2.0.0

opaqueConcur

Returns an concur iterable equivalent, but not referentially equal, to concurIterable.

Example

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' ]
Playground

Since

v2.0.0

pipe

Returns the result of piping value through the given functions.

Example

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' ]
Playground

Since

v0.0.1

Filters

FunctionDescription

exclude

Returns an iterable containing the values of iterable in iteration order excluding the values of excluded.

Example

import { exclude, pipe, reduce, toArray } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `active`, `sleep`, `awake`],
exclude([`awake`, `active`]),
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy', 'sleep' ]
Playground

Since

v2.0.0

excludeAsync

Returns an async iterable containing the values of asyncIterable in iteration order excluding the values of excluded.

Example

import { asAsync, excludeAsync, flatMapAsync, map, pipe, reduceAsync, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
flatMapAsync(async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return map(meaning => meaning.partOfSpeech, meanings)
}),
excludeAsync([`adjective`, `verb`]),
reduceAsync(toArray()),
),
)
//=> [ 'noun', 'noun' ]
Playground

Since

v2.0.0

excludeConcur

Returns a concur iterable containing the values of concurIterable in iteration order excluding the values of excluded.

Example

import { asConcur, excludeConcur, flatMapConcur, map, pipe, reduceConcur, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
flatMapConcur(async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return map(meaning => meaning.partOfSpeech, meanings)
}),
excludeConcur([`adjective`, `verb`]),
reduceConcur(toArray()),
),
)
//=> [ 'noun', 'noun' ]
Playground

Since

v2.0.0

filter

Returns an iterable that contains the values of iterable in iteration order excluding the values for which fn returns a falsy value.

Like Array.prototype.filter, but for iterables.

Example

import { filter, pipe, reduce, toArray } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
filter(word => word.startsWith(`s`)),
reduce(toArray()),
),
)
//=> [ 'sloth', 'sleep' ]
Playground

Since

v0.0.1

filterAsync

Returns an async iterable that contains the values of asyncIterable in iteration order excluding the values for which fn returns a value awaitable to a falsy value.

Like Array.prototype.filter, but for async iterables.

Example

import { asAsync, filterAsync, pipe, reduceAsync, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
filterAsync(async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.some(meaning => meaning.partOfSpeech === `adjective`)
}),
reduceAsync(toArray()),
),
)
//=> [ 'lazy' ]
Playground

Since

v0.0.1

filterConcur

Returns a concur iterable that contains the values of concurIterable excluding the values for which fn returns a value awaitable to a falsy value.

Like Array.prototype.filter, but for concur iterables.

Example

import { asConcur, filterConcur, pipe, reduceConcur, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
filterConcur(async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.some(meaning => meaning.partOfSpeech === `adjective`)
}),
reduceConcur(toArray()),
),
)
//=> [ 'lazy' ]
Playground

Since

v0.0.1

filterMap

Returns an iterable containing the values of iterable transformed by fn in iteration order excluding the values for which fn returns null or undefined.

Example

import { filterMap, pipe, reduce, toArray } from 'lfi'

console.log(
pipe(
[
{ sloth: `sloth` },
{ sloth: `lazy` },
{ notSloth: `active` },
{ sloth: `sleep` },
{ notSloth: `awake` },
],
filterMap(object => object.sloth),
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy', 'sleep' ]
Playground

Since

v0.0.1

filterMapAsync

Returns an async iterable containing the values of asyncIterable transformed by fn in iteration order excluding the values for which fn returns a value awaitable to null or undefined.

Example

import { asAsync, filterMapAsync, pipe, reduceAsync, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asAsync([
{ sloth: `sloth` },
{ sloth: `lazy` },
{ notSloth: `active` },
{ sloth: `sleep` },
{ notSloth: `awake` },
]),
filterMapAsync(async object => {
if (!object.sloth) {
return null
}

const response = await fetch(`${API_URL}/${object.sloth}`)
return (await response.json())[0].phonetic
}),
reduceAsync(toArray()),
),
)
//=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
Playground

Since

v0.0.1

filterMapConcur

Returns a concur iterable containing the values of concurIterable transformed by fn excluding the values for which fn returns a value awaitable to null or undefined.

Example

import { asConcur, filterMapConcur, pipe, reduceConcur, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asConcur([
{ sloth: `sloth` },
{ sloth: `lazy` },
{ notSloth: `active` },
{ sloth: `sleep` },
{ notSloth: `awake` },
]),
filterMapConcur(async object => {
if (!object.sloth) {
return null
}

const response = await fetch(`${API_URL}/${object.sloth}`)
return (await response.json())[0].phonetic
}),
reduceConcur(toArray()),
),
)
// NOTE: This order may change between runs
//=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
Playground

Since

v0.0.1

find

Returns an iterable containing the first value of iterable for which fn returns a truthy value. Otherwise, returns an empty iterable.

Like Array.prototype.find, but for iterables.

Example

import { find, or, pipe } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
find(word => word.includes(`s`)),
or(() => `not found!`),
),
)
//=> sloth

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
find(word => word.includes(`x`)),
or(() => `not found!`),
),
)
//=> not found!
Playground

Since

v0.0.1

findAsync

Returns an async iterable containing the first value of asyncIterable for which fn returns a value awaitable to a truthy value. Otherwise, returns an empty async iterable.

Like Array.prototype.find, but for async iterables.

Example

import { asAsync, findAsync, orAsync, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
findAsync(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
orAsync(() => `not found!`),
),
)
//=> sloth

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
findAsync(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
orAsync(() => `not found!`),
),
)
//=> not found!
Playground

Since

v0.0.1

findConcur

Returns a concur iterable containing the first value of concurIterable for which fn returns a value awaitable to a truthy value. Otherwise, returns an empty concur iterable.

Like Array.prototype.find, but for concur iterables.

Example

import { asConcur, findConcur, orConcur, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
findConcur(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
orConcur(() => `not found!`),
),
)
// NOTE: This word may change between runs
//=> sloth

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
findConcur(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
orConcur(() => `not found!`),
),
)
//=> not found!
Playground

Since

v0.0.1

findLast

Returns an iterable containing the last value of iterable for which fn returns a truthy value. Otherwise, returns an empty iterable.

Example

import { findLast, or, pipe } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
findLast(word => word.includes(`s`)),
or(() => `not found!`),
),
)
//=> sleep

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
findLast(word => word.includes(`x`)),
or(() => `not found!`),
),
)
//=> not found!
Playground

Since

v0.0.1

findLastAsync

Returns an async iterable containing the last value of asyncIterable for which fn returns a value awaitable to a truthy value. Otherwise, returns an empty async iterable.

Example

import { asAsync, findLastAsync, orAsync, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
findLastAsync(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
orAsync(() => `not found!`),
),
)
//=> sleep

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
findLastAsync(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
orAsync(() => `not found!`),
),
)
//=> not found!
Playground

Since

v0.0.1

findLastConcur

Returns a concur iterable containing the last value of concurIterable for which fn returns a value awaitable to a truthy value. Otherwise, returns an empty concur iterable.

Example

import { asConcur, findLastConcur, orConcur, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
findLastConcur(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
orConcur(() => `not found!`),
),
)
// NOTE: This word may change between runs
//=> sleep

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
findLastConcur(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
orConcur(() => `not found!`),
),
)
//=> not found!
Playground

Since

v0.0.2

unique

Returns an iterable containing the values of iterable in iteration order, except values are deduplicated if they are equal using Object.is.

Example

import { pipe, reduce, toArray, unique } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `lazy`, `sleep`, `sloth`],
unique,
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy', 'sleep' ]
Playground

Since

v0.0.1

uniqueAsync

Returns an async iterable containing the values of asyncIterable in iteration order, except values are deduplicated if they are equal using Object.is.

Example

import { asAsync, flatMapAsync, map, pipe, reduceAsync, toArray, uniqueAsync } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
flatMapAsync(async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return map(meaning => meaning.partOfSpeech, meanings)
}),
uniqueAsync,
reduceAsync(toArray()),
),
)
//=> [ 'noun', 'verb', 'adjective' ]
Playground

Since

v0.0.2

uniqueBy

Returns an iterable containing the values of iterable in iteration order, except values for which fn returns the same value are deduplicated.

When values are deduplicated, the value earlier in iteration order wins.

Example

import { pipe, reduce, toArray, uniqueBy } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
uniqueBy(word => word.length),
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy' ]
Playground

Since

v0.0.1

uniqueByAsync

Returns an async iterable containing the values of asyncIterable in iteration order, except values for which fn returns a value awaitable to the same value are deduplicated.

When values are deduplicated, the value earlier in iteration order wins.

Example

import { asAsync, pipe, reduceAsync, toArray, uniqueByAsync } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
uniqueByAsync(async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings[0].partOfSpeech
}),
reduceAsync(toArray()),
),
)
//=> [ 'sloth', 'sleep' ]
Playground

Since

v0.0.2

uniqueByConcur

Returns a concur iterable containing the values of concurIterable, except values for which fn returns a value awaitable to the same value are deduplicated.

When values are deduplicated, the value earlier in iteration order wins.

Example

import { asConcur, pipe, reduceConcur, toArray, uniqueByConcur } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
uniqueByConcur(async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings[0].partOfSpeech
}),
reduceConcur(toArray()),
),
)
// NOTE: These words may change between runs
//=> [ 'sloth', 'sleep' ]
Playground

Since

v0.0.2

uniqueConcur

Returns a concur iterable containing the values of concurIterable in iteration order, except values are deduplicated if they are equal using Object.is.

Example

import { asConcur, flatMapConcur, map, pipe, reduceConcur, toArray, uniqueConcur } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
flatMapConcur(async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return map(meaning => meaning.partOfSpeech, meanings)
}),
uniqueConcur,
reduceConcur(toArray()),
),
)
// NOTE: This order may change between runs
//=> [ 'noun', 'verb', 'adjective' ]
Playground

Since

v0.0.2

Generators

Type alias, FunctionDescription

RangeIterable

An iterable that yields integers in a range.

See RangeIterable.step for obtaining a new iterable that skips integers in steps.

Since

v2.0.0

cycle

Returns an infinite iterable that repeatedly yields the values of iterable in iteration order.

WARNING: This function does not buffer the values of iterable for future cycles. It reiterates iterable each cycle.

Example

import { cycle, join, pipe, take } from 'lfi'

console.log(
pipe(
cycle([`sloth`, `lazy`]),
take(6),
join(`, `),
),
)
//=> sloth, lazy, sloth, lazy, sloth, lazy
Playground

Since

v0.0.1

cycleAsync

Returns an infinite async iterable that repeatedly yields the values of asyncIterable.

WARNING: This function does not buffer the values of asyncIterable for future cycles. It reiterates asyncIterable each cycle.

Example

import { asAsync, cycleAsync, joinAsync, mapAsync, pipe, takeAsync } 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
}),
cycleAsync,
takeAsync(6),
joinAsync(`, `),
),
)
//=> /slɑθ/, /ˈleɪzi/, /sliːp/, /slɑθ/, /ˈleɪzi/, /sliːp/
Playground

Since

v0.0.1

entries

Returns an iterable containing the entries of object.

This differs from Map.prototype.entries in that the returned iterable can be iterated multiple times and differs from Object.entries in that the returned iterable is opaque.

Example

import { entries, pipe, reduce, toArray } from 'lfi'

console.log(
pipe(
entries([`sloth`, `lazy`, `sleep`]),
reduce(toArray()),
),
)
//=> [
//=> [ 0, 'sloth' ],
//=> [ 1, 'lazy' ],
//=> [ 2, 'sleep' ]
//=> ]

console.log(
pipe(
entries({
sloth: 1,
lazy: 2,
sleep: 3,
}),
reduce(toArray()),
),
)
//=> [
//=> [ 'sloth', 1 ],
//=> [ 'lazy', 2 ],
//=> [ 'sleep', 3 ]
//=> ]

console.log(
pipe(
entries(
new Map([
[`sloth`, 1],
[`lazy`, 2],
[`sleep`, 3],
]),
),
reduce(toArray()),
),
)
//=> [
//=> [ 'sloth', 1 ],
//=> [ 'lazy', 2 ],
//=> [ 'sleep', 3 ]
//=> ]
Playground

Since

v0.1.0

generate

Returns an infinite iterable that yields seed for its first value and then yields the result of applying fn to its previously yielded value for every subsequent value.

Example

import { generate, pipe, reduce, take, toArray } from 'lfi'

console.log(
pipe(
`sloth`,
generate(previousValue => `${previousValue} ${previousValue}`),
take(4),
reduce(toArray()),
),
)
//=> [
//=> 'sloth',
//=> 'sloth sloth',
//=> 'sloth sloth sloth sloth',
//=> 'sloth sloth sloth sloth sloth sloth sloth sloth'
//=> ]
Playground

Since

v0.0.1

generateAsync

Returns an infinite async iterable that yields seed for its first value and then yields the awaited result of applying fn to its previously yielded value for every subsequent value.

Example

import { generateAsync, pipe, reduceAsync, takeAsync, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

console.log(
await pipe(
`sleep`,
generateAsync(async previousWord => {
const response = await fetch(`${API_URL}/${previousWord}`)
const [{ meanings }] = await response.json()
return meanings[0].partOfSpeech
}),
takeAsync(4),
reduceAsync(toArray()),
),
)
//=> [ 'sleep', 'verb', 'noun', 'noun' ]
Playground

Since

v0.0.1

keys

Returns an iterable containing the keys of object.

This differs from Map.prototype.keys in that the returned iterable can be iterated multiple times and differs from Object.keys in that the returned iterable is opaque.

Example

import { keys, pipe, reduce, toArray } from 'lfi'

console.log(
pipe(
keys([`sloth`, `lazy`, `sleep`]),
reduce(toArray()),
),
)
//=> [ 0, 1, 2 ]

console.log(
pipe(
keys({
sloth: 1,
lazy: 2,
sleep: 3,
}),
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy', 'sleep' ]

console.log(
pipe(
keys(
new Map([
[`sloth`, 1],
[`lazy`, 2],
[`sleep`, 3],
]),
),
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy', 'sleep' ]
Playground

Since

v0.1.0

rangeTo

Returns a RangeIterable that yields the integers between start and end, including start and end.

Throws

if either start or end is not an integer.

Example

import { join, pipe, rangeTo } from 'lfi'

console.log(
pipe(
rangeTo(0, 6),
join(`, `),
),
)
//=> 0, 1, 2, 3, 4, 5, 6

console.log(
pipe(
rangeTo(0, 6).step(2),
join(`, `),
),
)
//=> 0, 2, 4, 6
Playground

Since

v0.0.1

rangeUntil

Returns a RangeIterable that yields the integers between start and end including start, but excluding end.

Throws

if either start or end is not an integer.

Example

import { join, pipe, rangeUntil } from 'lfi'

console.log(
pipe(
rangeUntil(0, 6),
join(`, `),
),
)
//=> 0, 1, 2, 3, 4, 5

console.log(
pipe(
rangeUntil(0, 6).step(2),
join(`, `),
),
)
//=> 0, 2, 4
Playground

Since

v0.0.1

repeat

Returns an infinite iterable that repeatedly yields value.

Example

import { join, pipe, repeat, take } from 'lfi'

console.log(
pipe(
repeat(`sloth`),
take(4),
join(`, `),
),
)
//=> sloth, sloth, sloth, sloth
Playground

Since

v0.0.1

values

Returns an iterable containing the values of object.

This differs from Map.prototype.values and Set.prototype.values in that the returned iterable can be iterated multiple times and differs from Object.values in that the returned iterable is opaque.

Example

import { pipe, reduce, toArray, values } from 'lfi'

console.log(
pipe(
values([`sloth`, `lazy`, `sleep`]),
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy, 'sleep' ]

console.log(
pipe(
values({
sloth: 1,
lazy: 2,
sleep: 3,
}),
reduce(toArray()),
),
)
//=> [ 1, 2, 3 ]

console.log(
pipe(
values(new Set([`sloth`, `lazy`, `sleep`])),
reduce(toArray()),
),
)
//=> [ 'sloth', 'lazy, 'sleep' ]

console.log(
pipe(
values(
new Map([
[`sloth`, 1],
[`lazy`, 2],
[`sleep`, 3],
]),
),
reduce(toArray()),
),
)
//=> [ 1, 2, 3 ]
Playground

Since

v0.1.0

Optionals

Type alias, FunctionDescription

AsyncOptional

An async iterable containing exactly zero or one values.

Since

v2.0.0

ConcurOptional

A concur iterable containing exactly zero or one values.

Since

v2.0.0

Optional

An iterable containing exactly zero or one values.

Since

v2.0.0

get

Returns the only value in iterable if it contains exactly one value. Otherwise, throws an error.

Example

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...
Playground

Since

v0.0.1

getAsync

Returns a promise that resolves to the only value in asyncIterable if it contains exactly one value. Otherwise, returns a promise that rejects.

Example

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...
Playground

Since

v0.0.1

getConcur

Returns a promise that resolves to the only value in concurIterable if it contains exactly one value. Otherwise, returns a promise that rejects.

Example

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...
Playground

Since

v0.0.2

next

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

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
Playground

Since

v0.0.1

nextAsync

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

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
Playground

Since

v0.0.1

or

Returns the only value in iterable if it contains exactly one value. Otherwise, returns the result of invoking fn.

Example

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!
Playground

Since

v0.0.1

orAsync

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

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???
Playground

Since

v0.0.1

orConcur

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.

Example

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???
Playground

Since

v0.0.2

Predicates

FunctionDescription

all

Returns true if fn returns a truthy value for all values of iterable. Otherwise returns false.

Like Array.prototype.every, but for iterables.

Example

import { all, pipe } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
all(word => word.includes(`l`)),
),
)
//=> true

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
all(word => word.includes(`s`)),
),
)
//=> false
Playground

Since

v0.0.1

allAsync

Returns a promise that resolves to true if fn returns a truthy value or a promise that resolves to a truthy value for all values of asyncIterable. Otherwise returns a promise that resolves to false.

Like Array.prototype.every, but for async iterables.

Example

import { allAsync, asAsync, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
allAsync(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
),
)
//=> true

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
allAsync(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
),
)
//=> false
Playground

Since

v0.0.1

allConcur

Returns a promise that resolves to true if fn returns a truthy value or a promise that resolves to a truthy value for all values of concurIterable. Otherwise returns a promise that resolves to false.

Like Array.prototype.every, but for concur iterables.

Example

import { allConcur, asConcur, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
allConcur(async word => (await getPartsOfSpeech(word)).includes(`verb`)),
),
)
//=> true

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
allConcur(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
),
)
//=> false
Playground

Since

v0.0.2

any

Returns true if fn returns a truthy value for any value of iterable. Otherwise returns false.

Like Array.prototype.some, but for iterables.

Example

import { any, pipe } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
any(word => word.includes(`s`)),
),
)
//=> true

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
any(word => word.includes(`x`)),
),
)
//=> false
Playground

Since

v0.0.1

anyAsync

Returns a promise that resolves to true if fn returns a truthy value or a promise that resolves to a truthy value for any value of asyncIterable. Otherwise returns a promise that resolves to false.

Like Array.prototype.some, but for async iterables.

Example

import { anyAsync, asAsync, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
anyAsync(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
),
)
//=> true

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
anyAsync(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
),
)
//=> false
Playground

Since

v0.0.1

anyConcur

Returns a promise that resolves to true if fn returns a truthy value or a promise that resolves to a truthy value for any value of concurIterable. Otherwise returns a promise that resolves to false.

Like Array.prototype.some, but for concur iterables.

Example

import { anyConcur, asConcur, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
anyConcur(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
),
)
//=> true

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
anyConcur(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
),
)
//=> false
Playground

Since

v0.0.2

includes

Returns true if any value of iterable is equal to searchElement using Object.is. Otherwise returns false.

Like Array.prototype.includes, but for iterables.

Example

import { includes, pipe } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
includes(`lazy`),
),
)
//=> true

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
includes(`awake`),
),
)
//=> false
Playground

Since

v0.0.2

includesAsync

Returns a promise that resolves to true if any value of asyncIterable is equal to searchElement using Object.is. Otherwise returns a promise that resolves to false.

Like Array.prototype.includes, but for async iterables.

Example

import { asAsync, flatMapAsync, includesAsync, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
flatMapAsync(getPartsOfSpeech),
includesAsync(`noun`),
),
)
//=> true

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
flatMapAsync(getPartsOfSpeech),
includesAsync(`adverb`),
),
)
//=> false
Playground

Since

v0.0.2

includesConcur

Returns a promise that resolves to true if any value of concurIterable is equal to searchElement using Object.is. Otherwise returns a promise that resolves to false.

Like Array.prototype.includes, but for concur iterables.

Example

import { asConcur, flatMapConcur, includesConcur, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
flatMapConcur(getPartsOfSpeech),
includesConcur(`noun`),
),
)
//=> true

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
flatMapConcur(getPartsOfSpeech),
includesConcur(`adverb`),
),
)
//=> false
Playground

Since

v0.0.2

none

Returns true if fn returns a falsy value for all values of iterable. Otherwise returns false.

Example

import { none, pipe } from 'lfi'

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
none(word => word.includes(`s`)),
),
)
//=> false

console.log(
pipe(
[`sloth`, `lazy`, `sleep`],
none(word => word.includes(`x`)),
),
)
//=> true
Playground

Since

v0.0.1

noneAsync

Returns a promise that resolves to true if fn returns a falsy value or a promise that resolves to a falsy value for all values of asyncIterable. Otherwise returns a promise that resolves to false.

Example

import { noneAsync, asAsync, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
noneAsync(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
),
)
//=> false

console.log(
await pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
noneAsync(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
),
)
//=> true
Playground

Since

v0.0.1

noneConcur

Returns a promise that resolves to true if fn returns a falsy value or a promise that resolves to a falsy value for all values of concurIterable. Otherwise returns a promise that resolves to false.

Example

import { noneConcur, asConcur, pipe } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`
const getPartsOfSpeech = async word => {
const response = await fetch(`${API_URL}/${word}`)
const [{ meanings }] = await response.json()
return meanings.map(meaning => meaning.partOfSpeech)
}

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
noneConcur(async word => (await getPartsOfSpeech(word)).includes(`noun`)),
),
)
//=> true

console.log(
await pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
noneConcur(async word => (await getPartsOfSpeech(word)).includes(`adverb`)),
),
)
//=> false
Playground

Since

v0.0.2

Reducers

Type alias, Variable, FunctionDescription

AsyncFunctionReducer

An async reducer that reduces by combining pairs of values using function application.

Since

v2.0.0

AsyncKeyedReducer

An async keyed reducer that reduces by creating an initial accumulator using RawAsyncReducerWithoutFinish.create and then adding key-value pairs to the accumulator values using RawAsyncReducerWithoutFinish.add. The async keyed reducer is optionally able to combine pairs of accumulators using RawAsyncReducerWithoutFinish.combine. The accumulator can be queried for values by key using RawAsyncKeyedReducer.get.

Since

v2.0.0

AsyncOptionalReducer

An async reducer that reduces by combining pairs of values using RawAsyncOptionalReducerWithoutFinish.add and then transforming the final value using RawAsyncOptionalReducerWithFinish.finish.

Since

v2.0.0

AsyncReducer

An async reducer that reduces by creating an initial accumulator using RawAsyncReducerWithoutFinish.create, then adding values to the accumulator values using RawAsyncReducerWithoutFinish.add, and then transforming the final accumulator using RawAsyncReducerWithFinish.finish. The async reducer is optionally able to combine pairs of accumulators using RawAsyncReducerWithoutFinish.combine.

Since

v2.0.0

FunctionReducer

A reducer that reduces by combining pairs of values using function application.

Example

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
Playground

Since

v2.0.0

KeyedReducer

A keyed reducer that reduces by creating an initial accumulator using RawReducerWithoutFinish.create and then adding key-value pairs to the accumulator values using RawReducerWithoutFinish.add. The accumulator can be queried for values by key using RawKeyedReducer.get.

Since

v2.0.0

OptionalReducer

A reducer that reduces by combining pairs of values using RawOptionalReducerWithoutFinish.add and then transforming the final value using RawOptionalReducerWithFinish.finish.

It's identical to RawOptionalReducerWithFinish except its this is bound by normalizeReducer.

Example

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
Playground

Since

v2.0.0

RawAsyncKeyedReducer

An async keyed reducer that reduces by creating an initial accumulator using RawAsyncReducerWithoutFinish.create and then adding key-value pairs to the accumulator values using RawAsyncReducerWithoutFinish.add. The async keyed reducer is optionally able to combine pairs of accumulators using RawAsyncReducerWithoutFinish.combine. The accumulator can be queried for values by key using RawAsyncKeyedReducer.get.

Since

v2.0.0

RawAsyncOptionalReducerWithFinish

An async reducer that reduces by combining pairs of values using RawAsyncOptionalReducerWithoutFinish.add and then transforming the final value using RawAsyncOptionalReducerWithFinish.finish.

Since

v2.0.0

RawAsyncOptionalReducerWithoutFinish

An async reducer that reduces by combining pairs of values using RawAsyncOptionalReducerWithoutFinish.add.

Since

v2.0.0

RawAsyncReducerWithFinish

An async reducer that reduces by creating an initial accumulator using RawAsyncReducerWithoutFinish.create, then adding values to the accumulator values using RawAsyncReducerWithoutFinish.add, and then transforming the final accumulator using RawAsyncReducerWithFinish.finish. The async reducer is optionally able to combine pairs of accumulators using RawAsyncReducerWithoutFinish.combine.

Since

v2.0.0

RawAsyncReducerWithoutFinish

An async reducer that reduces by creating an initial accumulator using RawAsyncReducerWithoutFinish.create and then adding values to the accumulator values using RawAsyncReducerWithoutFinish.add. The async reducer is optionally able to combine pairs of accumulators using RawAsyncReducerWithoutFinish.combine.

Since

v2.0.0

RawKeyedReducer

A keyed reducer that reduces by creating an initial accumulator using RawReducerWithoutFinish.create and then adding key-value pairs to the accumulator values using RawReducerWithoutFinish.add. The accumulator can be queried for values by key using RawKeyedReducer.get.

Since

v2.0.0

RawOptionalReducerWithFinish

A reducer that reduces by combining pairs of values using RawOptionalReducerWithoutFinish.add and then transforming the final value using RawOptionalReducerWithFinish.finish.

Example

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
Playground

Since

v2.0.0

RawOptionalReducerWithoutFinish

A reducer that reduces by combining pairs of values using RawOptionalReducerWithoutFinish.add.

Example

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
Playground

Since

v2.0.0

RawReducerWithFinish

A reducer that reduces by creating an initial accumulator using RawReducerWithoutFinish.create, then adding values to the accumulator values using RawReducerWithoutFinish.add, and then transforming the final accumulator using RawReducerWithFinish.finish.

Example

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
Playground

Since

v2.0.0

RawReducerWithoutFinish

A reducer that reduces by creating an initial accumulator using RawReducerWithoutFinish.create and then adding values to the accumulator values using RawReducerWithoutFinish.add.

Example

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
Playground

Since

v2.0.0

Reducer

A reducer that reduces by creating an initial accumulator using RawReducerWithoutFinish.create, then adding values to the accumulator values using RawReducerWithoutFinish.add, and then transforming the final accumulator using RawReducerWithFinish.finish.

It's identical to RawReducerWithFinish except its this is bound by normalizeReducer.

Example

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
Playground

Since

v2.0.0

NO_ENTRY

A unique value representing the lack of an entry for some key in a KeyedReducer or 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.

Since

v2.0.0

mapAsyncReducer

Returns an AsyncReducer equivalent to reducer except its final value is transformed using fn.

Since

v2.0.0

mapReducer

Returns a Reducer or OptionalReducer equivalent to reducer except its final value is transformed using fn.

Since

v2.0.0

normalizeReducer

Returns a non-raw version of reducer.

Since

v2.0.0

reduce

Returns the result of reducing iterable using reducer.

An initial accumulator is created using RawReducerWithoutFinish.create. Then each value in iterable is added to the accumulator and the current accumulator is updated using RawReducerWithoutFinish.add. Finally, the resulting accumulator is transformed using RawReducerWithFinish.finish if specified.

If reducer is an optional reducer (no 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

console.log(
pipe(
[`Hello`, `Sloth!`, `What`, `an`, `interesting`, `program!`],
reduce((a, b) => `${a} ${b}`),
get,
),
)
//=> Hello Sloth! What an interesting program!

console.log(
pipe(
[`Hello`, `Sloth!`, `What`, `an`, `interesting`, `program!`],
reduce({ create: () => ``, add: (a, b) => `${a} ${b}` }),
),
)
//=> Hello Sloth! What an interesting program!

Since

v0.0.1

reduceAsync

Returns the result of reducing the asyncIterable using asyncReducer.

Informally, an initial accumulator is created using RawAsyncReducerWithoutFinish.create. Then each value in asyncIterable is added to the accumulator and the current accumulator is updated using RawAsyncReducerWithoutFinish.add. Finally, the resulting accumulator is transformed using RawAsyncReducerWithFinish.finish if specified. Multiple accumulators may be created, added to, and then combined if supported via RawAsyncReducerWithoutFinish.combine and the next value of asyncIterable is ready before promises from RawAsyncReducerWithoutFinish.add resolve.

If asyncReducer is an async optional reducer (no 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

console.log(
await pipe(
asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
reduceAsync((a, b) => `${a} ${b}`),
getAsync,
),
)
//=> Hello World! What an interesting program!

console.log(
await pipe(
asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
reduceAsync({ create: () => ``, add: (a, b) => `${a} ${b}` }),
),
)
//=> Hello World! What an interesting program!

Since

v0.0.1

reduceConcur

Returns the result of reducing the concurIterable using asyncReducer.

Informally, an initial accumulator is created using RawAsyncReducerWithoutFinish.create. Then each value in concurIterable is added to the accumulator and the current accumulator is updated using RawAsyncReducerWithoutFinish.add. Finally, the resulting accumulator is transformed using RawAsyncReducerWithFinish.finish if specified. Multiple accumulators may be created, added to, and then combined if supported via RawAsyncReducerWithoutFinish.combine and the next value of concurIterable is ready before promises from RawAsyncReducerWithoutFinish.add resolve.

If asyncReducer is an async optional reducer (no 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

console.log(
await pipe(
asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
reduceAsync((a, b) => `${a} ${b}`),
getAsync,
),
)
//=> Hello World! What an interesting program!

console.log(
await pipe(
asAsync([`Hello`, `World!`, `What`, `an`, `interesting`, `program!`]),
reduceAsync({ create: () => ``, add: (a, b) => `${a} ${b}` }),
),
)
//=> Hello World! What an interesting program!

Since

v0.0.1

Side effects

FunctionDescription

cache

Returns an iterable equivalent to iterable that iterates over iterable at most once by lazily caching the values from the first iteration.

Example

import { each, cache, pipe } from 'lfi'

const iterable = pipe(
[`sloth`, `lazy`, `sleep`],
each(console.log),
cache,
)
// No output

console.log([...iterable])
//=> sloth
//=> lazy
//=> sleep
//=> [ 'sloth', 'lazy', 'sleep' ]

console.log([...iterable])
//=> [ 'sloth', 'lazy', 'sleep' ]
Playground

Since

v2.0.0

cacheAsync

Returns an async iterable equivalent to asyncIterable that iterates over asyncIterable at most once by lazily caching the values from the first iteration.

Example

import { asAsync, eachAsync, cacheAsync, mapAsync, pipe, reduceAsync, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

const asyncIterable = pipe(
asAsync([`sloth`, `lazy`, `sleep`]),
mapAsync(async word => {
const response = await fetch(`${API_URL}/${word}`)
return (await response.json())[0].phonetic
}),
eachAsync(console.log),
cacheAsync,
)
// No output

console.log(
await pipe(
asyncIterable,
reduceAsync(toArray()),
),
)
//=> /slɑθ/
//=> /ˈleɪzi/
//=> /sliːp/
//=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]

console.log(
await pipe(
asyncIterable,
reduceAsync(toArray()),
),
)
//=> [ '/slɑθ/', '/ˈleɪzi/', '/sliːp/' ]
Playground

Since

v2.0.0

cacheConcur

Returns a concur iterable equivalent to concurIterable that iterates over concurIterable at most once by lazily caching the values from the first iteration.

Example

import { asConcur, eachConcur, cacheConcur, mapConcur, pipe, reduceConcur, toArray } from 'lfi'

const API_URL = `https://api.dictionaryapi.dev/api/v2/entries/en`

const asyncIterable = pipe(
asConcur([`sloth`, `lazy`, `sleep`]),
mapConcur(async word => {
const response = await fetch(`${API_URL}/${word}`)
return (await response.json())[0].phonetic
}),
eachConcur(console.log),
cacheConcur,
)
// No output

console.log(
await pipe(
asyncIterable,
reduceConcur(toArray()),
),
)
// NOTE: This order may change between runs
//=> /slɑθ/