iterama v0.6.1
iterama 
Composable functional (async) iterable helpers.
Install
yarn add iteramaAPI
- iterama !npm
- Install
- API
concatconcatAsyncdistinctdistinctAsyncfilterfilterAsyncforEachforEachAsynciterateiterateAsynclengthlengthAsyncmapmapAsyncrangerangeAsyncreducereduceAsyncscanscanAsyncskipskipAsyncslicesliceAsyncstartWithstartWithAsynctaketakeAsyncuniqueuniqueAsynczipzipAsynctoArraytoArrayAsynctoSettoSetAsynctoObjecttoObjectAsynctoMaptoMapAsynctoIteratortoIteratorAsynctoValuetoValueAsync
In the examples below we use range() and rangeAsync() helpers whenever possible just to save space and reading time.
range(5) is the same as [0, 1, 2, 3, 4] array (because arrays are iterables too), or, in a more low-level manner:
{
*[Symbol.iterator]() {
for (let i = 0; i < 5; i++) {
yield i
}
}
}and rangeAsync(5) is:
{
async *[Symbol.asyncIterator]() {
for (let i = 0; i < 5; i++) {
yield await Promise.resolve(i)
}
}
}concat
Concatenates multiple iterables.
const concat: <T>(iterables: Iterable<Iterable<T>>) => Iterable<T>import { concat } from 'iterama'
const iterable1 = [1, 2, 3]
const iterable2 = [4, 5, 6]
const result = concat([iterable1, iterable2])
for (const value of result)
console.log(value)
}
// 1
// 2
// 3
// 4
// 5
// 6concatAsync
Concatenates multiple async iterables.
const concatAsync: <T>(iterables: Iterable<AsyncIterable<T>>) => AsyncIterable<T>import { concatAsync } from 'iterama'
const iterable1 = {
async *[Symbol.asyncIterable]() {
for (let i = 1; i <= 3; i++) {
yield await Promise.resolve(i)
}
}
}
const iterable2 = {
async *[Symbol.asyncIterable]() {
for (let i = 4; i <= 6; i++) {
yield await Promise.resolve(i)
}
}
}
const result = concatAsync([iterable1, iterable2])
for await (const value of result)
console.log(value)
}
// 1
// 2
// 3
// 4
// 5
// 6distinct
Distincts (squashes repeatable) iterable values.
const distinct: <T>(iterable: Iterable<T>) => Iterable<T>import { distinct } from 'iterama'
const result = distinct([1, 1, 3, 3, 4, 3])
for (const value of result) {
console.log(value)
}
// 1
// 3
// 4
// 3distinctAsync
Distincts (squashes repeatable) async iterable values.
const distinctAsync: <T>(iterable: AsyncIterable<T>) => AsyncIterable<T>import { distinctAsync } from 'iterama'
const iterable = {
async *[Symbol.asyncIterable]() {
yield await Promise.resolve(1)
yield await Promise.resolve(1)
yield await Promise.resolve(3)
yield await Promise.resolve(3)
yield await Promise.resolve(4)
yield await Promise.resolve(3)
}
}
const result = distinctAsync(iterable)
for await (const value of result) {
console.log(value)
}
// 1
// 3
// 4
// 3filter
Filters iterable values.
type TFilterFn<T> = (arg: T, index: number) => boolean
const filter: <T>(filterFn: TFilterFn<T>) => (iterable: Iterable<T>) => Iterable<T>import { filter, range } from 'iterama'
const iterable = range(5)
const isEven = (x: number) => x % 2 === 0
const result = filter(isEven)(iterable)
for (const value of result) {
console.log(value)
}
// 0
// 2
// 4filterAsync
Filters async iterable values.
type TFilterFnAsync<T> = (arg: T, index: number) => Promise<boolean> | boolean
const filterAsync: <T>(filterFn: TFilterFnAsync<T>) => (iterable: AsyncIterable<T> | Iterable<T>) => AsyncIterable<T>import { filterAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const isEven = (x: number) => x % 2 === 0
const result = filterAsync(isEven)(iterable)
for await (const value of result) {
console.log(value)
}
// 0
// 2
// 4forEach
Invokes callback with iterable values.
type TForEachFn<T> = (value: T, i: number) => void
const forEach: <T>(forEachFn: TForEachFn<T>) => (iterable: Iterable<T>) => Iterable<T>import { forEach, range } from 'iterama'
const iterable = range(5)
const result = forEach(console.log)(iterable)
for (const value of result) {
console.log(value)
}
// 0 0
// 0
// 1 1
// 1
// 2 2
// 2
// 3 3
// 3
// 4 4
// 4forEachAsync
Invokes callback with async iterable values.
type TForEachFnAsync<T> = (value: T, i: number) => Promise<void> | void
const forEachAsync: <T>(forEachFn: TForEachFnAsync<T>) => (iterable: AsyncIterable<T> | Iterable<T>) => AsyncIterable<T>import { forEachAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const result = forEachAsync(async (value, i) => {
await Promise.resolve()
console.log(value, i)
})(iterable)
for await (const value of result) {
console.log(value)
}
// 0 0
// 0
// 1 1
// 1
// 2 2
// 2
// 3 3
// 3
// 4 4
// 4iterate
Provides iterable iterator out of iterable.
const iterate: <T>(iterable: Iterable<T>): IterableIterator<T>import { iterate, range } from 'iterama'
const iterable = range(5)
const iterator = iterate(iterable)
console.log(iterator.next().value)
// 0
console.log(iterator.next().value)
// 1
for (const value of iterator) {
console.log(value)
}
// 2
// 3
// 4iterateAsync
Provides async iterable iterator out of async iterable.
const iterateAsync: <T>(iterable: AsyncIterable<T>): AsyncIterableIterator<T>import { iterateAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const iterator = iterateAsync(iterable)
console.log((await iterator.next()).value)
// 0
console.log((await iterator.next()).value)
// 1
for await (const value of iterator) {
console.log(value)
}
// 2
// 3
// 4length
Returns length of iterable, limited to Number.MAX_SAFE_INTEGER.
const length: <T>(iterable: Iterable<T>) => numberimport { length, range } from 'iterama'
const iterable = range(5)
const result = length(iterable)
console.log(result)
// 5lengthAsync
Returns length of async iterable, limited to Number.MAX_SAFE_INTEGER.
const lengthAsync: <T>(iterable: AsyncIterable<T>) => Promise<number>import { lengthAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const result = await lengthAsync(iterable)
console.log(result)
// 5map
Maps over iterable.
type TMapFn<T, R> = (value: T, i: number) => R
const map: <T, R>(mapFn: TMapFn<T, R>) => (iterable: Iterable<T>) => Iterable<R>import { map } from 'iterama'
const iterable = range(5)
const mult2 = (x: number) => x * 2
const result = map(mult2)(iterable)
for (const value of result) {
console.log(value)
}
// 0
// 2
// 4
// 6
// 8mapAsync
Maps over async iterable.
type TMapFnAsync<T, R> = (value: T, i: number) => Promise<R> | R
const mapAsync: <T, R>(mapFn: TMapFnAsync<T, R>) => (iterable: AsyncIterable<T> | Iterable<T>) => AsyncIterable<R>import { mapAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const mult2 = (x: number) => Promise.resolve(x * 2)
const result = mapAsync(mult2)(iterable)
for await (const value of result) {
console.log(value)
}
// 0
// 2
// 4
// 6
// 8range
Provides iterable filled with numbers from zero to given length.
const range: (length: number) => Iterable<number>import { range } from 'iterama'
const result = range(5)
for (const value of result) {
console.log(value)
}
// 0
// 1
// 2
// 3
// 4rangeAsync
Provides async iterable filled with numbers from zero to given length.
const rangeAsync: (length: number) => AsyncIterable<number>import { rangeAsync } from 'iterama'
const result = rangeAsync(5)
for await (const value of result) {
console.log(value)
}
// 0
// 1
// 2
// 3
// 4reduce
Reduces over iterable.
type TReduceFn<T, R> = (acc: R, value: T, index: number) => R
const reduce: <T, R>(reduceFn: TReduceFn<T, R>, initial: R) => (iterable: Iterable<T>) => Iterable<R>import { reduce, range } from 'iterama'
const iterable = range(5)
const reducer = (acc: number, value: number) => acc + value
const result = reduce(reducer, 0)(iterable)
for (const value of result) {
console.log(value)
}
// 10reduceAsync
Reduces over async iterable.
type TReduceFnAsync<T, R> = (acc: R, value: T, index: number) => Promise<R> | R
const reduceAsync: <T, R>(reduceFn: TReduceFnAsync<T, R>, initial: Promise<R> | R) => (iterable: AsyncIterable<T> | Iterable<T>) => AsyncIterable<R>import { reduceAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const reducer = (acc: number, value: number) => Promise.resolve(acc + value)
const result = reduceAsync(reducer, Promise.resolve(0))(iterable)
for await (const value of result) {
console.log(value)
}
// 10scan
Scans over iterable. Like reduce but returns iterable with values from every step.
type TScanFn<T, R> = (acc: R, value: T, index: number) => R
const scan: <T, R>(scanFn: TScanFn<T, R>, initial: R) => (iterable: Iterable<T>) => Iterable<R>import { scan } from 'iterama'
const iterable = range(5)
const scanner = (acc: number, value: number) => Promise.resolve(acc + value)
const result = scan(scanner, 0)(iterable)
for (const value of result) {
console.log(value)
}
// 0
// 1
// 3
// 6
// 10scanAsync
Scans over async iterable. Like reduce but returns async iterable with values from every step.
type TScanFnAsync<T, R> = (acc: R, value: T, index: number) => Promise<R> | R
const scanAsync: <T, R>(scanFn: TScanFnAsync<T, R>, initial: Promise<R> | R) => (iterable: AsyncIterable<T> | Iterable<T>) => AsyncIterable<R>import { scanAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const scanner = (acc: number, value: number) => Promise.resolve(acc + value)
const result = scanAsync(scanner, 0)(iterable)
for await (const value of result) {
console.log(value)
}
// 0
// 1
// 3
// 6
// 10skip
Skips n first/last iterable values.
const skip: (n: number) => <T>(iterable: Iterable<T>) => Iterable<T>import { skip, range } from 'iterama'
const iterable1 = range(5)
const result1 = skip(2)(iterable1)
for (const value of result1) {
console.log(value)
}
// 2
// 3
// 4
const iterable2 = range(5)
const result2 = skip(-2)(iterable2)
for (const value of result2) {
console.log(value)
}
// 0
// 1
// 2skipAsync
Skips n first/last async iterable values.
const skipAsync: (n: number) => <T>(iterable: AsyncIterable<T>) => AsyncIterable<T>import { skipAsync, rangeAsync } from 'iterama'
const iterable1 = rangeAsync(5)
const result1 = skipAsync(2)(iterable1)
for await (const value of result1) {
console.log(value)
}
// 2
// 3
// 4
const iterable2 = rangeAsync(5)
const result2 = skipAsync(-2)(iterable2)
for await (const value of result2) {
console.log(value)
}
// 0
// 1
// 2slice
Slices iterable.
const slice: (from?: number, to?: number) => <T>(iterable: Iterable<T>) => Iterable<T>import { slice, range } from 'iterama'
const iterable1 = range(5)
// skip 1, take 2
const result1 = slice(1, 2)(iterable1)
for (const value of result1) {
console.log(value)
}
// 1
// 2
const iterable2 = range(5)
// skip until 2 from end, take 1
const result2 = slice(-2, 1)(iterable2)
for (const value of result2) {
console.log(value)
}
// 3
const iterable3 = range(5)
// don't skip, take last 2
const result3 = slice(0, -2)(iterable3)
for (const value of result3) {
console.log(value)
}
// 0
// 1
// 2
const iterable4 = range(5)
// skip 2, take the rest
const result4 = slice(2)(iterable4)
for (const value of result4) {
console.log(value)
}
// 2
// 3
// 4
const iterable5 = range(5)
// skip until 2 from end, take the rest
const result5 = slice(-2)(iterable5)
for (const value of result4) {
console.log(value)
}
// 3
// 4
const iterable6 = range(5)
// don't skip, take all
const result6 = slice()(iterable6)
for (const value of result6) {
console.log(value)
}
// 0
// 1
// 2
// 3
// 4sliceAsync
Slices async iterable.
const sliceAsync: (from?: number, to?: number) => <T>(iterable: AsyncIterable<T>) => AsyncIterable<T>import { sliceAsync, rangeAsync } from 'iterama'
const iterable1 = rangeAsync(5)
// skip 1, take 2
const result1 = sliceAsync(1, 2)(iterable1)
for await (const value of result1) {
console.log(value)
}
// 1
// 2
const iterable2 = rangeAsync(5)
// skip until 2 from end, take 1
const result2 = sliceAsync(-2, 1)(iterable2)
for await (const value of result2) {
console.log(value)
}
// 3
const iterable3 = rangeAsync(5)
// don't skip, take last 2
const result3 = sliceAsync(0, -2)(iterable3)
for await (const value of result3) {
console.log(value)
}
// 0
// 1
// 2
const iterable4 = rangeAsync(5)
// skip 2, take the rest
const result4 = sliceAsync(2)(iterable4)
for await (const value of result4) {
console.log(value)
}
// 2
// 3
// 4
const iterable5 = rangeAsync(5)
// skip until 2 from end, take the rest
const result5 = sliceAsync(-2)(iterable5)
for await (const value of result4) {
console.log(value)
}
// 3
// 4
const iterable6 = rangeAsync(5)
// don't skip, take all
const result6 = sliceAsync()(iterable6)
for await (const value of result6) {
console.log(value)
}
// 0
// 1
// 2
// 3
// 4startWith
Starts iterable with additional value.
const startWith: <T>(value: T) => (iterable: Iterable<T>) => Iterable<T>import { startWith, range } from 'iterama'
const iterable = range(5)
const result = startWith(-1)(iterable)
for (const value of result) {
console.log(value)
}
// -1
// 0
// 1
// 2
// 3
// 4startWithAsync
Starts async iterable with additional value.
const startWithAsync: <T>(value: T) => (iterable: AsyncIterable<T>) => AsyncIterable<T>import { startWithAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const result = startWithAsync(-1)(iterable)
for await (const value of result) {
console.log(value)
}
// -1
// 0
// 1
// 2
// 3
// 4take
Takes n first/last iterable values.
const take: (n: number) => <T>(iterable: Iterable<T>) => Iterable<T>import { take, range } from 'iterama'
const iterable1 = range(5)
// take 2 first, skip the rest
const result1 = take(2)(iterable1)
for (const value of result1) {
console.log(value)
}
// 0
// 1
const iterable2 = range(5)
// take 2 last
const result2 = take(-2)(iterable2)
for (const value of result1) {
console.log(value)
}
// 3
// 4takeAsync
Takes n first/last async iterable values.
const takeAsync: (n: number) => <T>(iterable: AsyncIterable<T>) => AsyncIterable<T>import { takeAsync, rangeAsync } from 'iterama'
const iterable1 = rangeAsync(5)
// take 2 first, skip the rest
const result1 = takeAsync(2)(iterable1)
for await (const value of result1) {
console.log(value)
}
// 0
// 1
const iterable2 = rangeAsync(5)
// take 2 last
const result2 = takeAsync(-2)(iterable2)
for await (const value of result1) {
console.log(value)
}
// 3
// 4unique
Takes unique iterable values.
const unique: <T>(iterable: Iterable<T>) => Iterable<T>import { unique } from 'iterama'
const iterable = {
*[Symbol.iterator]() {
yield 1
yield 1
yield 3
yield 4
yield 3
}
}
const result = unique(iterable)
for (const value of result) {
console.log(value)
}
// 1
// 3
// 4uniqueAsync
Takes unique async iterable values.
const uniqueAsync: <T>(iterable: AsyncIterable<T>) => AsyncIterable<T>import { uniqueAsync } from 'iterama'
const iterable = {
async *[Symbol.asyncIterator]() {
yield await Promise.resolve(1)
yield await Promise.resolve(1)
yield await Promise.resolve(3)
yield await Promise.resolve(4)
yield await Promise.resolve(4)
}
}
const result = uniqueAsync(iterable)
for await (const value of result) {
console.log(value)
}
// 1
// 3
// 4zip
Zips (combines) multiple iterables.
const zip: <A, B>(iterable0: Iterable<A>, iterable1: Iterable<B>) => Iterable<[A, B]>
const zip: <A, B, C>(iterable0: Iterable<A>, iterable1: Iterable<B>, iterable2: Iterable<C>) => Iterable<[A, B, C]>
const zip: <A, B, C, D>(iterable0: Iterable<A>, iterable1: Iterable<B>, iterable2: Iterable<C>, iterable3: Iterable<D>) => Iterable<[A, B, C, D]>import { zip, range } from 'iterama'
const iterable1 = range(5)
const iterable2 = {
*[Symbol.iteratior]() {
yield 'a'
yield 'b'
yield 'c'
yield 'd'
}
}
const result = zip(iterable1, iterable2)
for (const value of result) {
console.log(value)
}
// [0, 'a'],
// [1, 'b'],
// [2, 'c'],
// [3, 'd']zipAsync
Zips (combines) multiple async iterables.
const zipAsync: <A, B>(iterable0: AsyncIterable<A>, iterable1: AsyncIterable<B>) => AsyncIterable<[A, B]>
const zipAsync: <A, B, C>(iterable0: AsyncIterable<A>, iterable1: AsyncIterable<B>, iterable2: AsyncIterable<C>) => AsyncIterable<[A, B, C]>
const zipAsync: <A, B, C, D>(iterable0: AsyncIterable<A>, iterable1: AsyncIterable<B>, iterable2: AsyncIterable<C>, iterable3: AsyncIterable<D>) => AsyncIterable<[A, B, C, D]>import { zipAsync, rangeAsync } from 'iterama'
const iterable1 = rangeAsync(5)
const iterable2 = {
async *[Symbol.asyncIteratior]() {
yield await Promise.resolve('a')
yield await Promise.resolve('b')
yield await Promise.resolve('c')
yield await Promise.resolve('d')
}
}
const result = zipAsync(iterable1, iterable2)
for await (const value of result) {
console.log(value)
}
// [0, 'a'],
// [1, 'b'],
// [2, 'c'],
// [3, 'd']toArray
Converts iterable into array.
const toArray: <T>(iterable: Iterable<T>) => T[]import { toArray, range } from 'iterama'
const iterable = range(5)
const result = toArray(iterable)
console.log(result)
// [0, 1, 2, 3, 4]toArrayAsync
Converts async iterable into array.
const toArrayAsync: <T>(iterable: AsyncIterable<T>) => Promise<T[]>import { toArrayAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const result = await toArrayAsync(iterable)
console.log(result)
// [0, 1, 2, 3, 4]toSet
Converts iterable into Set.
const toSet: <T>(iterable: Iterable<T>) => Set<T>import { toSet, range } from 'iterama'
const iterable = range(5)
const result = toSet(iterable)
console.log(result)
// Set(5) [ 0, 1, 2, 3, 4 ]toSetAsync
Converts async iterable into Set.
const toSetAsync: <T>(iterable: AsyncIterable<T>) => Promise<Set<T>>import { toSetAsync, rangeAsync } from 'iterama'
const iterable = rangeAsync(5)
const result = await toSetAsync(iterable)
console.log(result)
// Set(5) [ 0, 1, 2, 3, 4 ]toObject
Converts iterable filled with entries into object.
const toObject: <K extends PropertyKey, V>(iterable: Iterable<readonly [K, V]>) => { [key in K]: V }import { toObject } from 'iterama'
const iterable = {
*[Symbol.iterator]() {
yield ['a', 0]
yield ['b', 1]
yield ['c', 2]
yield ['d', 3]
yield ['e', 4]
}
}
const result = toObject(iterable)
console.log(result)
// {
// a: 0,
// b: 1,
// c: 2,
// d: 3,
// e: 4,
// }toObjectAsync
Converts async iterable filled with entries into object.
const toObject: <K extends PropertyKey, V>(iterable: AsyncIterable<readonly [K, V]>) => Promise<{ [key in K]: V }>import { toObjectAsync } from 'iterama'
const iterable = {
async *[Symbol.asyncIterator]() {
yield await Promise.resolve(['a', 0])
yield await Promise.resolve(['b', 1])
yield await Promise.resolve(['c', 2])
yield await Promise.resolve(['d', 3])
yield await Promise.resolve(['e', 4])
}
}
const result = await toObjectAsync(iterable)
console.log(result)
// {
// a: 0,
// b: 1,
// c: 2,
// d: 3,
// e: 4,
// }toMap
Converts iterable filled with entries into Map.
const toMap: <K, V>(iterable: Iterable<readonly [K, V]>) => Map<K, V>import { toMap } from 'iterama'
const iterable = {
*[Symbol.iterator]() {
yield ['a', 0]
yield ['b', 1]
yield ['c', 2]
yield ['d', 3]
yield ['e', 4]
}
}
const result = toMap(iterable)
console.log(result)
// Map {
// a → 0,
// b → 1,
// c → 2,
// d → 3,
// e → 4
// }toMapAsync
Converts async iterable filled with entries into Map.
const toMapAsync: <K, V>(iterable: AsyncIterable<readonly [K, V]>) => Promise<Map<K, V>>import { toMapAsync } from 'iterama'
const iterable = {
async *[Symbol.asyncIterator]() {
yield await Promise.resolve(['a', 0])
yield await Promise.resolve(['b', 1])
yield await Promise.resolve(['c', 2])
yield await Promise.resolve(['d', 3])
yield await Promise.resolve(['e', 4])
}
}
const result = await toMapAsync(iterable)
console.log(result)
// Map {
// a → 0,
// b → 1,
// c → 2,
// d → 3,
// e → 4
// }toIterator
Extracts iterator from iterable.
const toIterator: <T>(iterable: Iterable<T>) => Iterator<T>import { toIterator } from 'iterama'
const iterable = {
*[Symbol.iterator]() {
yield 1
yield 2
yield 3
}
}
const iterator = toIterator(iterable)
const result = [
iterator.next(),
iterator.next(),
iterator.next(),
iterator.next(),
]
console.log(result)
// [
// { value: 1, done: false },
// { value: 2, done: false },
// { value: 3, done: false },
// { value: undefined, done: true },
// ]toIteratorAsync
Extracts async iterator from async iterable.
const toAsyncIterator: <T>(iterable: AsyncIterable<T>) => AsyncIterator<T>import { toIteratorAsync } from 'iterama'
const iterable = {
*[Symbol.asyncIterator]() {
yield Promise.resolve(1)
yield Promise.resolve(2)
yield Promise.resolve(3)
}
}
const iterator = toIteratorAsync(iterable)
const result = [
await iterator.next(),
await iterator.next(),
await iterator.next(),
await iterator.next(),
]
console.log(result)
// [
// { value: 1, done: false },
// { value: 2, done: false },
// { value: 3, done: false },
// { value: undefined, done: true },
// ]toValue
Extracts first value from iterable.
const toValue: <T>(iterable: Iterable<T>) => T | undefinedimport { toValue } from 'iterama'
const iterable = {
*[Symbol.iterator]() {
yield 1
yield 2
}
}
const value = toValue(iterable)
console.log(result)
// 1toValueAsync
Extracts first value from async iterable.
const toAsyncIterator: <T>(iterable: AsyncIterable<T>) => Promise<T | undefined>import { toValueAsync } from 'iterama'
const iterable = {
*[Symbol.asyncIterator]() {
yield Promise.resolve(1)
yield Promise.resolve(2)
}
}
const value = await toValueAsync(iterable)
console.log(value)
// 1