funk-lib

Functional JavaScript Library

CircleCI npm module

For a full list of functions see the Documentation For The Latest Release.

Install

npm i -P funk-lib
# or: es-module compatible build
npm i -P funk-lib-es

Import

const { mapKeys } = require('funk-lib/object');
// or: es-module compatible build
import { mapKeys } from 'funk-lib-es/object';

Development

Commands

$ npm run <command>

command description
build Transpile source
cover Run test coverage
init Re/Install deps
init:hard init with a fresh package-lock
docs parse docs to json
lint Lint the source
test Run tests
test:watch Run tests on change
verify Verify linting, tests, coverage
array
code

array

Functions for working with Array

const { array } = require('funk-lib');
array.clear
code

array/clear

[a] → []

Delete all items. mutating + identity

const { clear } = require('funk-lib/array');

const arr = [1, 2, 3];
clear(arr); // arr === []
array.sample
code

array/sample

[a] → a

Select a random array item

const { sample } = require('funk-lib/array');

sample([0, 1, 2, 3, 4, 5]); // 2
array.shuffle
code

array/shuffle

[a] → [a]

Immutably randomize array element order Fisher-Yates shuffle

const { shuffle } = require('funk-lib/array');

shuffle([1, 2, 3, 4, 5]); // [4, 1, 2, 5, 3]
array.toObj
code

array/toObj

[ k: v ] → { k: v }

Transform an array into an object, where keys are indices, and values are elements.

const { toObj } = require('funk-lib/array');

toObj(['a', 'b', 'c']); // { 0: a, 1: b, 2: c }
async
code

async

Functions for working with promises, async + await, and parallelism

const { async } = require('funk-lib');
async.all
code

async/all

[Promise<a>] → [a]

Resolve promises in parallel

const { all } = require('funk-lib/async');

// [1, 2, 3]
await all([
  Promise.resolve(1),
  2,
  Promise.resolve(3),
]);
async.allSettled
code

async/allSettled

[Promise] → Promise<[{ status, value, reason }]>

All settled

const { allSettled } = require('funk-lib/async');

// [
//   { status: 'fulfilled', value: 1 },
//   { status: 'rejected', reason: Error('oops') },
// ]
await allSettled([
  Promise.resolve(1),
  Promise.reject(Error('oops')),
]);
async.callbackify
code

async/callbackify

Make a promise-returning function errback-yielding. Inverse of promisify

const { callbackify } = require('funk-lib/async');

const func = async n => n + 1;
await callbackify(func)(1, (err, res) => {
  // err = null, res = 2
});
async.defer
code

async/defer

(a → b) → Promise<b>

Defers invoking a function until the current call stack has cleared

const { defer } = require('funk-lib/async');

await defer(_ => 3); // 3
async.deferWith
code

async/deferWith

[a] → (a → b) → Promise<b>

Defers invoking a function until the current call stack has cleared. Passes args to deferred function.

const { deferWith } = require('funk-lib/async');

await deferWith([1, 2], (a, b) => a + b); // 3
async.deferred
code

async/deferred

* → Object

Creates an externally controlled promise

const { deferred } = require('funk-lib/async');

const { promise, resolve, reject } = deferred();
resolve(123);
await promise; // 123
async.delay
code

async/delay

Number → Promise<undefined>

Creates a promise that resolves in n ms

const { delay } = require('funk-lib/async');

await delay(100); // resolved in 100ms
async.every
code

async/every

(a → Promise<Boolean>) → [a] → Promise<Boolean>

Parallel every

const { every } = require('funk-lib/async');

// false
await every(async n => (n > 5), [4, 5, 6, 7]);
async.everyLimit
code

async/everyLimit

Number → (a → Promise<Boolean>) → [a] → Promise<Boolean>

Every with variable parallelization

const { everyLimit } = require('funk-lib/async');

// false
await everyLimit(2, async n => (n > 4), [1, 2, 3, 4, 5]);
async.everySeries
code

async/everySeries

(a → Promise<Boolean>) → [a] → Promise<Boolean>

Serial every

const { everySeries } = require('funk-lib/async');

// false
await everySeries(async n => (n > 5), [4, 5, 6, 7]);
async.evolve
code

async/evolve

{ k: (a → Promise<b>) } → { k: a } → Promise<{ k: b }>

Async R.evolve

const { evolve } = require('funk-lib/async');

const data = { a: 1, b: 2, c: 3 };
// { a: 2, b: 4, c: 3 }
await evolve({
  a: async a => a + 1,
  b: async b => b * 2,
}, data);
async.filter
code

async/filter

(a → Promise<Boolean>) → [a] → Promise<[a]>

Parallel filter

const { filter } = require('funk-lib/async');

const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// [0, 1, 2, 3, 4, 5]
await filter(async n => (n <= 5), array);
async.filterLimit
code

async/filterLimit

Number → (a → Promise<Boolean>) → [a] → Promise<[a]>

Filter with variable parallelization

const { filterLimit } = require('funk-lib/async');

// [1, 2]
await filterLimit(2, async n => (n < 3), [1, 2, 3, 4, 5]);
async.filterSeries
code

async/filterSeries

(a → Promise<Boolean>) → [a] → Promise<[a]>

Serial filter

const { filterSeries } = require('funk-lib/async');

const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// [0, 1, 2, 3, 4, 5]
await filterSeries(async n => (n <= 5), array);
async.find
code

async/find

(a → Promise<Boolean>) → [a] → Promise<a>

Parallel find

const { find } = require('funk-lib/async');

const records = [{ id: 1 }, { id: 2 }, { id: 3 }];

// { id: 2 }
await find(async ({ id }) => (id === 2), records);
async.findLimit
code

async/findLimit

Number → (a → Promise<Boolean>) → [a] → Promise<a>

Find with variable parallelization

const { findLimit } = require('funk-lib/async');

const records = [{ id: 1 }, { id: 2 }, { id: 3 }];

// { id: 2 }
await findLimit(2, async ({ id }) => (id === 2), records);
async.findSeries
code

async/findSeries

(a → Promise<Boolean>) → [a] → Promise<a>

Serial find

const { findSeries } = require('funk-lib/async');

const records = [{ id: 1 }, { id: 2 }, { id: 3 }];

// { id: 2 }
await findSeries(async ({ id }) => (id === 2), records);
async.flatMap
code

async/flatMap

(a → Promise<[b]>) → [a] → Promise<[b]>

Parallel flatMap (aka. "chain")

const { flatMap } = require('funk-lib/async');

// [1, 2, 2, 4, 3, 6]
await flatMap(async n => [n, n * 2], [1, 2, 3]);
async.flatMapLimit
code

async/flatMapLimit

Number → (a → Promise<[b]>) → [a] → Promise<[b]>

Flat map (aka. "chain") with variable parallelization

const { flatMapLimit } = require('funk-lib/async');

// [1, 2, 2, 4, 3, 6]
await flatMapLimit(2, async n => [n, n * 2], [1, 2, 3]);
async.flatMapPairs
code

async/flatMapPairs

([a, b] → Promise<[[c, d]]>) → { a: b } → Promise<{ c: d }>

Parallel flat map pairs

const { flatMapPairs } = require('funk-lib/async');

// { 2: 2, b: b }
flatMapPairs(([a, b]) => {
  return (b > 1) ? [[a, a], [b, b]] : [];
}, { a: 1, b: 2 });
async.flatMapPairsLimit
code

async/flatMapPairsLimit

Number → ([a, b] → Promise<[[c, d]]>) → { a: b } → Promise<{ c: d }>

Flat map pairs with variable parallelization

const { flatMapPairsLimit } = require('funk-lib/async');

// { 2: 2, b: b }
flatMapPairsLimit(10, ([a, b]) => {
  return (b > 1) ? [[a, a], [b, b]] : [];
}, { a: 1, b: 2 });
async.flatMapPairsSeries
code

async/flatMapPairsSeries

([a, b] → Promise<[[c, d]]>) → { a: b } → Promise<{ c: d }>

Serial flat map pairs

const { flatMapPairsSeries } = require('funk-lib/async');

// { 2: 2, b: b }
flatMapPairsSeries(([a, b]) => {
  return (b > 1) ? [[a, a], [b, b]] : [];
}, { a: 1, b: 2 });
async.flatMapSeries
code

async/flatMapSeries

(a → Promise<[b]>) → [a] → Promise<[b]>

Serial flatMap (aka. "chain")

const { flatMapSeries } = require('funk-lib/async');

// [1, 2, 2, 4, 3, 6]
await flatMapSeries(async n => [n, n * 2], [1, 2, 3]);
async.forEach
code

async/forEach

(a → Promise<b>) → [a] → Promise<[a]>

Parallel for each

const { forEach } = require('funk-lib/async');

// log 1
// log 2
// log 3
// [1, 2, 3]
await forEach(async n => console.log(n), [1, 2, 3]);
async.forEachLimit
code

async/forEachLimit

Number → (a → Promise<b>) → [a] → Promise<[a]>

For each with variable parallelization

const { forEachLimit } = require('funk-lib/async');

// 1
// 2
// 3
await forEachLimit(2, async n => console.log(n), [1, 2, 3]);
async.forEachSeries
code

async/forEachSeries

(a → Promise<b>) → [a] → Promise<[a]>

Serial for each

const { forEachSeries } = require('funk-lib/async');

// log 1
// log 2
// log 3
// [1, 2, 3]
await forEachSeries(async n => console.log(n), [1, 2, 3]);
async.fromCallback
code

async/fromCallback

Returns a promise that is resolved by an err-back function

const { fromCallback } = require('funk-lib/async');

await fromCallback(cb => cb(null, 123)); // 123
await fromCallback(cb => cb(Error('oops'))); // Error('oops')
async.map
code

async/map

(a → Promise<b>) → [a] → Promise<[b]>

Parallel map

const { map } = require('funk-lib/async');

const array = [1, 2, 3, 4, 5];

// [2, 4, 6, 8, 10]
await map(async n => (n * 2), array);
async.mapLimit
code

async/mapLimit

Number → (a → Promise<b>) → [a] → Promise<[b]>

Map with variable parallelization

const { mapLimit } = require('funk-lib/async');

// [2, 4, 6, 8, 10]
await mapLimit(2, async n => (n * 2), [1, 2, 3, 4, 5]);
async.mapPairs
code

async/mapPairs

([a, b] → Promise<[c, d]>) → { a: b } → Promise<{ c: d }>

Parallel map pairs

const { mapPairs } = require('funk-lib/async');

// { 1: 'a', 2: 'b', 3: 'c' }
await mapPairs(async pair => pair.reverse(), { a: 1, b: 2, c: 3 });
async.mapPairsLimit
code

async/mapPairsLimit

Number → ([a, b] → Promise<[c, d]>) → { a: b } → Promise<{ c: d }>

Map pairs with variable parallelization

const { mapPairsLimit } = require('funk-lib/async');

// { 1: 'a', 2: 'b', 3: 'c' }
await mapPairsLimit(2, async pair => pair.reverse(), { a: 1, b: 2, c: 3 });
async.mapPairsSeries
code

async/mapPairsSeries

([a, b] → Promise<[c, d]>) → { a: b } → Promise<{ c: d }>

Serial map pairs

const { mapPairsSeries } = require('funk-lib/async');

// { 1: 'a', 2: 'b', 3: 'c' }
await mapPairsSeries(async pair => pair.reverse(), { a: 1, b: 2, c: 3 });
async.mapSeries
code

async/mapSeries

(a → Promise<b>) → [a] → Promise<[b]>

Serial map

const { mapSeries } = require('funk-lib/async');

const array = [1, 2, 3, 4, 5];

// [2, 4, 6, 8, 10]
await mapSeries(async n => (n * 2), array);
async.pipe
code

async/pipe

(...f) → f

Left-to-right function composition that works with sync or async functions

const { pipe } = require('funk-lib/async');

// 4
await pipe(
  async n => n + 1,
  async n => n * 2,
)(1);
async.pipeC
code

async/pipeC

(...f) → f

Curried async pipe

const { pipeC } = require('funk-lib/async');

const math = pipeC(
  async (a, b) => a + b,
  c => (c * 2),
  async c => (c + 1),
);
await math(2)(5) // 21;
async.promisify
code

async/promisify

Make an errback-calling function promise-returning. Inverse of callbackify

const { promisify } = require('funk-lib/async');

const callback = (n, cb) => cb(null, n + 1);
await promisify(callback)(1); // 2
async.props
code

async/props

{ k: Promise<v> } → Promise<{ k: v }>

Resolve object values in parallel

const { props } = require('funk-lib/async');

// { one: 1, two: 2, three: 3 }
await props({
  one: Promise.resolve(1),
  two: 2,
  three: Promise.resolve(3),
});
async.race
code

async/race

[Promise<a>] → a

Returns a promise that resolves or rejects as soon as one of the promises in an iterable resolves or rejects, with the value or reason from that promise.

const { race } = require('funk-lib/async');

// true
await race([
  delay(1).then(_ => true),
  delay(10).then(_ => false),
  delay(100).then(_ => { throw Error('oops') }),
]);
async.reduce
code

async/reduce

((a, b) → Promise<a>) → a → [b] → Promise<a>

Async reduce

const { reduce } = require('funk-lib/async');

// 15
await reduce(async (a, n) => a + n, 0, [1, 2, 3, 4, 5]);
async.reject
code

async/reject

Error → Promise<Error>

Create a rejected promise

const { reject } = require('funk-lib/async');

// Promise<Error('oops')>
reject(Error('oops'));
async.resolve
code

async/resolve

a → Promise<a>

Create a resolved promise

const { resolve } = require('funk-lib/async');

// Promise<1>
resolve(1);
async.retryWith
code

async/retryWith

Number → (a → b) → (a → Promise<b>)

Wrap a function to retry based on a predicate function

const { retryWith } = require('funk-lib/async');

// retry 10 times with exponential backoff
const retry = retryWith(i => {
  return (i < 10)
    ? return 50 * Math.pow(2, i)
    : false;
});
const data = await retry(getData)('https://foo.bar');
async.some
code

async/some

(a → Promise<Boolean>) → [a] → Promise<Boolean>

Parallel some

const { some } = require('funk-lib/async');

// true
await some(async n => (n > 5), [4, 5, 6, 7]);
async.someLimit
code

async/someLimit

Number → (a → Promise<Boolean>) → [a] → Promise<Boolean>

Some with variable parallelization

const { someLimit } = require('funk-lib/async');

// true
await someLimit(2, async n => (n > 4), [1, 2, 3, 4, 5]);
async.someSeries
code

async/someSeries

(a → Promise<Boolean>) → [a] → Promise<Boolean>

Serial some

const { someSeries } = require('funk-lib/async');

// true
await someSeries(async n => (n > 5), [4, 5, 6, 7]);
async.timeout
code

async/timeout

Number → Promise<a> → Promise<a>

Timeout a promise

const { timeout } = require('funk-lib/async');

await timeout(2000, delay(100)); // undefined
await timeout(100, delay(2000)); // TimeoutError
async.toAsync
code

async/toAsync

(a → b) → (a → Promise<b>)

Wraps a function to always return a promise

const { toAsync } = require('funk-lib/async');

const pred = n => n > 5;
const asyncPred = toAsync(pred);
asyncPred(2); // Promise<false>
color
code

color

Functions for generating and transforming colors

const { color } = require('funk-lib');
color.hexToHsl
code

color/hexToHsl

String → { h, s, l }

Hex to HSL

const { hexToHsl } = require('funk-lib/color');
color.hexToRgb
code

color/hexToRgb

String → { r, g, b }

Hex to RGB

const { hexToRgb } = require('funk-lib/color');
color.hslToHex
code

color/hslToHex

{ h, s, l } → String

HSL to hex

const { hslToHex } = require('funk-lib/color');
color.hslToRgb
code

color/hslToRgb

{ h, s, l } → { r, g, b }

HSL to RGB

const { hslToRgb } = require('funk-lib/color');
color.randomHex
code

color/randomHex

* → String

Get a random hex string

const { randomHex } = require('funk-lib/color');

randomHex(); // #b3a95a
color.randomHsl
code

color/randomHsl

* → { h, s, l }

Get a random HSL value

const { randomHsl } = require('funk-lib/color');
color.randomRgb
code

color/randomRgb

* → { r, g, b }

Get a random RGB value

const { randomRgb } = require('funk-lib/color');

randomRgb(); // { r: 35, g: 125, b: 106 }
color.rgbToHex
code

color/rgbToHex

{ r, g, b } → String

RGB to hex

const { rgbToHex } = require('funk-lib/color');
color.rgbToHsl
code

color/rgbToHsl

{ r, g, b } → { h, s, l }

RGB to HSL

const { rgbToHsl } = require('funk-lib/color');
crypto
code

crypto

Functions for cryptography

const { crypto } = require('funk-lib');
crypto.hashWith
code

crypto/hashWith

String → String → String

Hash with variable algorithm

const { hashWith } = require('funk-lib/crypto');

hashWith('md5', 'hello'); // '5d41402abc4b2a76b9719d911017c592'
crypto.md5
code

crypto/md5

String → String

md5 hash a string

const { md5 } = require('funk-lib/crypto');

md5('hello'); // '5d41402abc4b2a76b9719d911017c592'
crypto.sha256
code

crypto/sha256

String → String

sha256 hash a string

const { sha256 } = require('funk-lib/crypto');

sha256('hello'); // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
crypto.sha512
code

crypto/sha512

String → String

sha512 hash a string

const { sha512 } = require('funk-lib/crypto');

sha512('hello'); // 'E7C22B994C59D9CF2B48E549B1E24666636045930D3DA7C1ACB299D1C3B7F931F94AAE41EDDA2C2B207A36E10F8BCB8D45223E54878F5B316E7CE3B6BC019629'
datetime
code

datetime

Functions for date and time

const { datetime } = require('funk-lib');
datetime.now
code

datetime/now

a → Date

Get the current unix epoch (in ms)

const { now } = require('funk-lib/datetime');
function
code

function

Functions for working with Function

const { function } = require('funk-lib');
function.Y
code

function/Y

((a → b) → (a → b)) → (a → b)

Y combinator. Define recursive functions without variable assignment.

const { Y } = require('funk-lib/function');

const fib = Y(f => n => {
  return (n <= 2) ? 1 : f(n - 1) + f(n - 2);
});
fib(7); // 13
function.debounce
code

function/debounce

Number → (a → b) → (a → undefined)

Wrap a function to delay invocation until after delay ms have elapsed since the last call

const { debounce } = require('funk-lib/function');

const debounce = debounce(100, expensiveMath);
debounced(1, 2);
function.noop
code

function/noop

a → undefined

A function that does nothing. "no-op"

const { noop } = require('funk-lib/function');

noop(); // undefined
function.on
code

function/on

(b → b → c) → (a → b) → a → a → c

Transforms two inputs and combines the outputs

const { on } = require('funk-lib/function');

const records = [{ age: 9 }, { age: 1 }, { age: 3 }];

// [{ age: 1 }, { age: 3 }, { age: 9 }]
R.sort(on(R.subtract, R.prop('age'))), records);
function.once
code

function/once

(a → b) → (a → b)

Creates a function that is restricted to invoking func once. Repeat calls to the function return the value of the first invocation

const { once } = require('funk-lib/function');

const pred = n => n > 5;
const oncePred = once(pred);
oncePred(10); // true
oncePred(1); // true (cached. pred not called again)
function.pipeC
code

function/pipeC

...f → f

Curried pipe

const { pipeC } = require('funk-lib/function');

const math = pipeC(
  (a, b) => a + b,
  c => (c * 2),
  c => (c + 1),
);
math(2)(5) // 21;
function.throttle
code

function/throttle

Number → (a → b) → (a → b)

Wraps a function so that it is only invoked at most once every delay ms

const { throttle } = require('funk-lib/function');

const throttled = throttle(100, expensiveMath);
throttled(1, 2);
http
code

http

Functions for working with HTTP interfaces

const { http } = require('funk-lib');
http.parseContentType
code

http/parseContentType

String → { mimeType, charset, boundary }

Parse a content-type HTTP header into its parts

const { parseContentType } = require('funk-lib/http');

// {
//  mimeType: 'multipart/form-data',
//  boundary: 'abc',
//  charset: 'utf-8',
// }
parseContentType('multipart/form-data; boundary=abc; charset=utf-8');
// { mimeType: 'multipart/form-data' }
parseContentType('multipart/form-data');
is
code

is

Functions for typechecking

const { is } = require('funk-lib');
is.is
code

is/is

a → b → Boolean

Are two values equal by strict reference equality?

const { is } = require('funk-lib/is');

const sym = Symbol();
is(sym, sym); // true
is(1, true); // false
is.isArray
code

is/isArray

a → Boolean

Is a value an Array?

const { isArray } = require('funk-lib/is');

isArray([]); // true
is.isAsyncIterable
code

is/isAsyncIterable

a → Boolean

Is a value an async iterable?

const { isAsyncIterable } = require('funk-lib/is');

isAsyncIterable((async function* () {})()); // true
isAsyncIterable({ [Symbol.asyncIterator]: () => {} }); // true
is.isBoolean
code

is/isBoolean

a → Boolean

Is a value a Boolean?

const { isBoolean } = require('funk-lib/is');

isBoolean(false); // true
is.isBuffer
code

is/isBuffer

a → Boolean

Is a value a Buffer?

const { isBuffer } = require('funk-lib/is');

isBuffer(Buffer.from([])); // true
is.isDate
code

is/isDate

a → Boolean

Is a value a Date?

const { isDate } = require('funk-lib/is');

isDate(new Date()); // true
is.isEven
code

is/isEven

a → Boolean

Is a value even?

const { isEven } = require('funk-lib/is');

isEven(2); // true
isEven(3); // false
is.isFalsey
code

is/isFalsey

a → Boolean

Is a value falsey?

const { isFalsey } = require('funk-lib/is');

isFalsey(0); // true
is.isFinite
code

is/isFinite

a → Boolean

Is a value finite?

const { isFinite } = require('funk-lib/is');

isFinite(10); // true
isFinite(Infinity); // false
is.isFloat
code

is/isFloat

a → Boolean

Is a value a float?

const { isFloat } = require('funk-lib/is');

isFloat(1.23); // true
isFloat(1); // false
is.isFunction
code

is/isFunction

a → Boolean

Is a value a function?

const { isFunction } = require('funk-lib/is');

isFunction(() => {}); // true
is.isInstanceOf
code

is/isInstanceOf

String → a → Boolean

Is a value an instance of a class?

const { isInstanceOf } = require('funk-lib/is');

isInstanceOf(Array, []); // true
is.isInteger
code

is/isInteger

a → Boolean

Is a value an integer?

const { isInteger } = require('funk-lib/is');

isInteger(1); // true
isInteger(1.23); // false
is.isIterable
code

is/isIterable

a → Boolean

Is a value an iterable?

const { isIterable } = require('funk-lib/is');

isIterable([]); // true
isIterable({ [Symbol.iterator]: () => {} }); // true
is.isIterator
code

is/isIterator

a → Boolean

Is a value an iterator?

const { isIterator } = require('funk-lib/is');

const iterator = [][Symbol.iterator]();
isIterator(iterator); // true
is.isNaN
code

is/isNaN

a → Boolean

Is a value NaN?

const { isNaN } = require('funk-lib/is');

isNaN(NaN); // true
is.isNegative
code

is/isNegative

a → Boolean

Is a value negative?

const { isNegative } = require('funk-lib/is');

isNumber(-10); // true
isNumber(10); // false
is.isNot
code

is/isNot

a → b → Boolean

Are two values not equal by strict reference equality?

const { isNot } = require('funk-lib/is');

const sym = Symbol();
isNot(1, true); // true
isNot(sym, sym); // false
is.isNull
code

is/isNull

a → Boolean

Is a value null?

const { isNull } = require('funk-lib/is');

isNull(null); // true
is.isNumber
code

is/isNumber

a → Boolean

Is a value a number?

const { isNumber } = require('funk-lib/is');

isNumber(10); // true
isNumber(NaN); // false
is.isObject
code

is/isObject

a → Boolean

Is a value an object?

const { isObject } = require('funk-lib/is');

isObject({}); // true
isObject([]]); // false
isObject(null); // false
is.isOdd
code

is/isOdd

a → Boolean

Is a value odd?

const { isOdd } = require('funk-lib/is');

isOdd(1); // true
isOdd(2); // false
is.isPojo
code

is/isPojo

a → Boolean

Is a value a "plain old javascript object"?

const { isPojo } = require('funk-lib/is');

isPojo({}); // true
is.isPositive
code

is/isPositive

a → Boolean

Is a value positive?

const { isPositive } = require('funk-lib/is');

isNumber(10); // true
isNumber(-10); // false
is.isPromise
code

is/isPromise

a → Boolean

Is a value a promise?

const { isPromise } = require('funk-lib/is');

isPromise(Promise.resolve(1)); // true
is.isRegExp
code

is/isRegExp

a → Boolean

Is a value a regular expression?

const { isRegExp } = require('funk-lib/is');

isRegExp(/[a-z]/); // true
is.isStream
code

is/isStream

a → Boolean

Is a value a stream?

const { isStream } = require('funk-lib/is');

isStream(new Stream.Readable()); // true
is.isString
code

is/isString

a → Boolean

Is a value a string?

const { isString } = require('funk-lib/is');

isString('hello'); // true
is.isSymbol
code

is/isSymbol

a → Boolean

Is a value a symbol?

const { isSymbol } = require('funk-lib/is');

isSymbol(Symbol('foo')); // true
is.isTruthy
code

is/isTruthy

a → Boolean

Is a value truthy?

const { isTruthy } = require('funk-lib/is');

isTruthy(1); // true
is.isTypeOf
code

is/isTypeOf

String → a → Boolean

Does a value have a certin type (via typeof)?

const { isTypeOf } = require('funk-lib/is');

isTypeOf('boolean', true); // true
is.isUndefined
code

is/isUndefined

a → Boolean

Is a value undefined?

const { isUndefined } = require('funk-lib/is');

isUndefined(undefined); // true
iterable
code

iterable

A Module containing functions for working with sync and async iterables. Contains two symmetrical child modules: iterable/sync and iterable/async

const { iterable } = require('funk-lib');
iterable.async
code

iterable/async

Functions for working with async iterables

const { async } = require('funk-lib/iterable');
iterable.async.append
code

iterable/async/append

a → Iterable<a> → AsyncIterator<a>

Append an item a to the start of an iterable

const { append } = require('funk-lib/iterable/async');

append(4, from([1, 2, 3])); // AsyncIterator<1, 2, 3, 4>
iterable.async.concat
code

iterable/async/concat

Iterable<a> → Iterable<a> → AsyncIterator<a>

Yield all items from one async iterator, then the other

const { concat } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3, 4, 5, 6>
concat(from([1, 2, 3]), from([4, 5, 6]));
iterable.async.correspondsWith
code

iterable/async/correspondsWith

((a, b) → Promise<Boolean>) → Iterable<a> → Iterable<b> → Promise<Boolean>

Check if two async iterables match for every index with a custom comparator

const { correspondsWith } = require('funk-lib/iterable/async');

const one = from([{ id: 1 }, { id: 2 }, { id: 3 }]);
const two = from([{ id: 1 }, { id: 2 }, { id: 3 }]);
// true
await correspondsWith(R.prop('id'), one, two);
iterable.async.count
code

iterable/async/count

(a → Promise<Boolean>) → Iterable<a> → Promise<Integer>

Return the number of items in an iterable. exhasts input

const { count } = require('funk-lib/iterable/async');

// 4
await count(async n => (n > 3), from([1, 2, 3, 4, 5, 6, 7]));
iterable.async.cycle
code

iterable/async/cycle

Iterable<a> → AsyncIterator<a>

Yield iterable items cyclically, infinitely looping when the input is exhausted

const { cycle } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3, 1, 2, 3, ...>
cycle(from([1, 2, 3]));
iterable.async.cycleN
code

iterable/async/cycleN

Integer → Iterable<a> → AsyncIterator<a>

Yield all items from an iterator, n times

const { cycleN } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 1, 2, 1, 2>
cycleN(3, from([1, 2]));
iterable.async.drop
code

iterable/async/drop

Integer → Iterable<a> → AsyncIterator<a>

Drop the first n items of an iterable

const { drop } = require('funk-lib/iterable/async');

// AsyncIterator<4, 5>
drop(3, from(1, 2, 3, 4, 5));
iterable.async.dropLast
code

iterable/async/dropLast

Number → Iterable<a> → AsyncIterator<a>

Yield all but the last n items. note: caches n + 1 items

const { dropLast } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3>
dropLast(2, from([1, 2, 3, 4, 5]));
iterable.async.dropWhile
code

iterable/async/dropWhile

(a → Promise<Boolean>) → Iterable<a> → AsyncIterator<a>

Ignore yielded items until the predicate returns false

const { dropWhile } = require('funk-lib/iterable/async');

// AsyncIterator<5, 6, 1>
dropWhile(async n => (n < 5), from([2, 3, 4, 5, 6, 1]));
iterable.async.enumerate
code

iterable/async/enumerate

Iterable<a> → AsyncIterator<[Integer, a]>

Transform an iterable to an iterable of pairs of indices and their items

const { enumerate } = require('funk-lib/iterable/async');

// AsyncIterator<[0, 'zero'], [1, 'one'], [2, 'two']>
enumerate(from(['zero', 'one', 'two']));
iterable.async.every
code

iterable/async/every

(a → Promise<Boolean>) → Iterable<a> → Promise<Boolean>

Do all items pass their predicate?

const { every } = require('funk-lib/iterable/async');

// false
await every(async n => (n < 4), from([1, 2, 3, 4]));
iterable.async.exhaust
code

iterable/async/exhaust

Iterable<a> → Promise<undefined>

Yield all items

const { exhaust } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3>
const iterator = from([1, 2, 3]);
// AsyncIterator<>
await exhaust(iterator);
iterable.async.filter
code

iterable/async/filter

(a → Promise<Boolean>) → Iterable<a> → AsyncIterator<a>

Yield only items that pass the predicate

const { filter } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3, 4>
filter(async n => (n < 5), from([1, 2, 3, 4, 5, 6, 7, 8]));
iterable.async.find
code

iterable/async/find

(a → Promise<Boolean>) → Iterable<a> → Promise<a>

Find

const { find } = require('funk-lib/iterable/async');

const records = [{ id: 1 }, { id: 2 }, { id: 3 }];
// { id: 2 }
await find(async record => (record.id === 2), records);
iterable.async.findIndex
code

iterable/async/findIndex

(a → Promise<Boolean>) → Iterable<a> → Promise<Integer>

Find index

const { findIndex } = require('funk-lib/iterable/async');

const records = [{ id: 1 }, { id: 2 }, { id: 3 }];
// 1
await find(async record => (record.id === 2), records);
iterable.async.flatIterate
code

iterable/async/flatIterate

(a → Iterable<a>) → a → AsyncIterator<a>

Flat iterate

const { flatIterate } = require('funk-lib/iterable/async');

// AsyncIterator<0, 0, 1, 2, 2, 4, 3, 6, 4, 8, ...>
flatIterate(async function* (n) {
  yield await n;
  yield await (n * 2);
  return n + 1;
}, 0));
iterable.async.flatMap
code

iterable/async/flatMap

(a → Iterable<b>) → Iterable<a> → AsyncIterator<b>

Maps a function over an iterable and concatenates the results. a.k.a. "chain"

const { flatMap } = require('funk-lib/iterable/async');

const iterator = from([1, 2, 3]);

// AsyncIterator<1, 2, 2, 4, 3, 6>
flatMap(async function* (n) {
  yield await n;
  yield await n * 2;
}, iterator);
iterable.async.flatten
code

iterable/async/flatten

Iterable<Iterable<a>> → AsyncIterator<a>

Flattens a nested iterable of iterables into a single iterable

const { flatten } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3, 4>
unnest(from([1, [2, [3, [4]]]]));
iterable.async.flattenN
code

iterable/async/flattenN

Number → Iterable<Iterable<a>> → AsyncIterator<a>

Flattens n-levels of a nested iterable of iterables

const { flattenN } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3, [4]>
flattenN(2, from([1, [2, [3, [4]]]]))
iterable.async.forEach
code

iterable/async/forEach

(a → Promise<b>) → Iterable<a> → AsyncIterator<a>

Run a function (side-effect) once for each item

const { forEach } = require('funk-lib/iterable/async');

// log 1
// log 2
// log 3
// AsyncIterator<1, 2, 3>
forEach(console.log, from([1, 2, 3]));
iterable.async.frame
code

iterable/async/frame

Integer → Iterable<a> → AsyncIterator<[a]>

Yield a sliding "window" of length n. note: caches n items

const { frame } = require('funk-lib/iterable/async');

// AsyncIterator<[0, 1, 2], [1, 2, 3], [2, 3, 4], [4, 5, 6]>
frame(3, from([0, 1, 2, 3, 4, 5, 6]));
iterable.async.from
code

iterable/async/from

Iterable<a> → AsyncIterator<a>

Returns an async iterator from an iterable

const { from } = require('funk-lib/iterable/async');

from([1, 2, 3]); // AsyncIterator<1, 2, 3>
iterable.async.group
code

iterable/async/group

Iterable<a> → AsyncIterator<[a]>

Yield groups of items where the adjacent items are strictly equal

const { group } = require('funk-lib/iterable/async');

// AsyncIterator<[1, 1, 1], [2, 2], [3]>
group(from([1, 1, 1, 2, 2, 3]));
iterable.async.groupWith
code

iterable/async/groupWith

((a, a) → Promise<Boolean>) → Iterable<a> → AsyncIterator<[a]>

Yield groups of items where the predicate returns truthy for adjacent items

const { groupWith } = require('funk-lib/iterable/async');

// AsyncIterator<[1, 1, 1], [2, 2], [3]>
groupWith(async n => n, from([1, 1, 1, 2, 2, 3]));
iterable.async.indices
code

iterable/async/indices

Iterable<a> → AsyncIterator<Integer>

Get an iterator of indices (0 to length - 1)

const { indices } = require('funk-lib/iterable/async');

// AsyncIterator<0, 1, 2>
indices(from(['a', 'b', 'c']));
iterable.async.init
code

iterable/async/init

Iterable<a> → AsyncIterator<a>

Yield all but the last 1 item

const { init } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3, 4>
init(from([1, 2, 3, 4, 5]));
iterable.async.intersperse
code

iterable/async/intersperse

a → Iterable<a> → AsyncIterator<a>

Insert an item a between every item in the iterable

const { intersperse } = require('funk-lib/iterable/async');

// AsyncIterator<'a', '-', 'b', '-', 'c'>
intersperse('-', from('a', 'b', 'c'));
iterable.async.isEmpty
code

iterable/async/isEmpty

Iterable<a> → Promise<Boolean>

Is an iterable empty? (done or length = 0)

const { isEmpty } = require('funk-lib/iterable/async');

await isEmpty(from([])); // true
await isEmpty(from([1])); // false
iterable.async.iterate
code

iterable/async/iterate

(a → Promise<a>) → a → AsyncIterator<a>

Iterate infinitely, yielding items from seed through a predicate

const { iterate } = require('funk-lib/iterable/async');

// AsyncIterator<0, 2, 4, 6, 8, 10, ...>
iterate(async n => n + 2, 0);
iterable.async.join
code

iterable/async/join

Iterable<a> → Promise<String>

Serialize iterator items to a string

const { join } = require('funk-lib/iterable/async');

// 'abcde'
await join(from(['a', 'b', 'c', 'd', 'e']));
iterable.async.joinWith
code

iterable/async/joinWith

String → Iterable<a> → Promise<String>

Serialize iterator items to a string with an arbitrary spacer

const { joinWith } = require('funk-lib/iterable/async');

// 'some-slug-parts';
await joinWith('-', from(['some', 'slug', 'parts']));
iterable.async.last
code

iterable/async/last

Iterable<a> → Promise<a>

Returns the last item

const { last } = require('funk-lib/iterable/async');

await last(from(1, 2, 3)); // 3
iterable.async.length
code

iterable/async/length

Iterable<a> → Promise<Integer>

Get length of iterable

const { length } = require('funk-lib/iterable/async');

// 5
await length(from([1, 2, 3, 4, 5]));
iterable.async.map
code

iterable/async/map

(a → Promise<b>) → Iterable<a> → AsyncIterator<b>

Applies a function to each of an async iterable's yielded items. Works on all iterables

const { map } = require('funk-lib/iterable/async');

// AsyncIterator<2, 4, 6>
map(async n => n * 2, from([1, 2, 3]));
iterable.async.max
code

iterable/async/max

Iterable<Number> → Promise<Number>

Max

const { max } = require('funk-lib/iterable/async');

await max(from([1, 2, 3])); // 3
iterable.async.maxBy
code

iterable/async/maxBy

(a → Promise<Number>) → Iterable<a> → Promise<Number>

Max by

const { maxBy } = require('funk-lib/iterable/async');

const iterator = from([{ total: 1 }, { total: 2 }, { total: 3 }]);
// 3
await maxBy(R.prop('total'), iterator);
iterable.async.min
code

iterable/async/min

Iterable<Number> → Promise<Number>

Min

const { min } = require('funk-lib/iterable/async');

await min(from([1, 2, 3])); // 1
iterable.async.minBy
code

iterable/async/minBy

(a → Promise<Number>) → Iterable<a> → Promise<Number>

Min by

const { minBy } = require('funk-lib/iterable/async');

const iterator = from([{ total: 1 }, { total: 2 }, { total: 3 }]);
// 1
await minBy(R.prop('total'), iterator);
iterable.async.next
code

iterable/async/next

Iterable<a> → Promise<a>

Returns the first or "next" item. aka head

const { next } = require('funk-lib/iterable/async');

await next(from([1, 2, 3])); // 1
await next(from([])); // StopIterationError()
iterable.async.nextOr
code

iterable/async/nextOr

a → Iterable<a> → Promise<a>

Return the next item, or a default value if iterable is empty

const { nextOr } = require('funk-lib/iterable/async');

await nextOr(10, from([1, 2, 3])); // 1
await nextOr(10, from([])); // 10
iterable.async.none
code

iterable/async/none

(a → Promise<Boolean>) → Iterable<a> → Promise<Boolean>

Do all items fail the predicate?

const { none } = require('funk-lib/iterable/async');

// true
await none(async n => (n > 5), from([1, 2, 3, 4, 5]));
iterable.async.nth
code

iterable/async/nth

Integer → Iterable<a> → Promise<a>

Returns the element at the nth index

const { nth } = require('funk-lib/iterable/async');

// 'b'
await nth(1, from(['a', 'b', 'c', 'd']));
iterable.async.of
code

iterable/async/of

...a → AsyncIterator<a>

Create an iterator of one or more (variadic) arguments

const { of } = require('funk-lib/iterable/async');

of(1, 2, 3); // AsyncIterator<1, 2, 3>
iterable.async.pad
code

iterable/async/pad

a → Iterable<a> → AsyncIterator<a>

Pad iterable with an infinite number of items a

const { pad } = require('funk-lib/iterable/async');

// AsyncIterator<'a', 'b', 'c', 'd', 'd', 'd', ...>
pad('d', from(['a', 'b', 'c']));
iterable.async.padTo
code

iterable/async/padTo

Integer → a → Iterable<a> → AsyncIterator<a>

Pad an iterable with with a finite number of items a

const { padTo } = require('funk-lib/iterable/async');

// AsyncIterator<'a', 'b', 'c', 'd', 'd', 'd'>
padTo(6, 'd', from(['a', 'b', 'c']));
iterable.async.partition
code

iterable/async/partition

(a → Promise<Boolean>) → Iterable<a> → [AsyncIterator<a>, AsyncIterator<a>]

Split an aynsc iterable into a pair of iterables based on the truthiness of their predicate

const { partition } = require('funk-lib/iterable/async');

// [AsyncIterator<0, 1, 2>, AsyncIterator<3, 4, 5, 6>]
partition(async n => n < 3, from([0, 1, 2, 3, 4, 5, 6]));
iterable.async.prepend
code

iterable/async/prepend

a → Iterable<a> → AsyncIterator<a>

Prepend an item a to the end of an iterable

const { prepend } = require('funk-lib/iterable/async');

// AsyncIterator<0, 1, 2, 3>
prepend(0, from([1, 2, 3]));
iterable.async.range
code

iterable/async/range

Number → Number → AsyncIterator<Number>

Iterates from 0 to n - 1 (exclusive)

const { range } = require('funk-lib/iterable/async');

range(0, 5); // AsyncIterator<0, 1, 2, 3, 4>
iterable.async.rangeStep
code

iterable/async/rangeStep

Number → Number → Number → AsyncIterator<Number>

Iterates from 0 to n by with a step (exclusive)

const { rangeStep } = require('funk-lib/iterable/async');

// AsyncIterator<0, 15, 30, 45, 60, 75, 90>
rangeStep(15, 0, 100);
iterable.async.reduce
code

iterable/async/reduce

((a, b) → Promise<a>) → a → Iterable<b> → Promise<a>

Reduce

const { reduce } = require('funk-lib/iterable/async');

// 6
await reduce(async (a, b) => a + b, 0, from([1, 2, 3]));
iterable.async.reject
code

iterable/async/reject

(a → Promise<Boolean>) → Iterable<a> → AsyncIterator<a>

Yield only items that do not pass the predicate

const { reject } = require('funk-lib/iterable/async');

// AsyncIterator<6, 7, 8>
reject(async n => (n < 5), from(1, 2, 3, 4, 5, 6, 7, 8));
iterable.async.repeat
code

iterable/async/repeat

a → AsyncIterator<a>

Infinitely yield an item (a)

const { repeat } = require('funk-lib/iterable/async');

// AsyncIterator<'hi', 'hi', 'hi', ...>
repeat('hi');
iterable.async.reverse
code

iterable/async/reverse

Iterable<a> → AsyncIterator<a>

Reverse

const { reverse } = require('funk-lib/iterable/async');

reverse(from([1, 2, 3])); // AsyncIterator<3, 2, 1>
iterable.async.scan
code

iterable/async/scan

((a, b) → Promise<a>) → a → Iterable<b> → AsyncIterator<a>

Scan

const { scan } = require('funk-lib/iterable/async');

// AsyncIterator<1, 1, 2, 6, 24>
scan(R.multiply, 1, from([1, 2, 3, 4]));
iterable.async.slice
code

iterable/async/slice

Integer → Integer → Iterable<a> → AsyncIterator<a>

Slice an async iterator between two indices

const { slice } = require('funk-lib/iterable/async');

// AsyncIterator<3, 4, 5>
slice(2, 5, from([1, 2, 3, 4, 5, 6, 7, 8]));
iterable.async.some
code

iterable/async/some

(a → Promise<Boolean>) → Iterable<a> → Promise<Boolean>

Does any item pass the predicate?

const { some } = require('funk-lib/iterable/async');

// true
await some(async n => (n > 5), from([1, 2, 3, 4, 5, 6]));
iterable.async.sort
code

iterable/async/sort

((a, a) → Promise<Number>) → Iterable<a> → AsyncIterator<a>

Sort

const { sort } = require('funk-lib/iterable/async');

// AsyncIterator<'c', 'b', 'a'>
sort(async (a, b) => b.localeCompare(a), from(['a', 'b', 'c']));
iterable.async.splitAt
code

iterable/async/splitAt

Integer → Iterable<a> → [AsyncIterator<a>, AsyncIterator<a>]

Split an async iterable into a pair of iterables at a particular index

const { splitAt } = require('funk-lib/iterable/async');

// [AsyncIterator<0, 1, 2, 3, 4>, AsyncIterator<5, 6>]
splitAt(4, from([0, 1, 2, 3, 4, 5, 6]));
iterable.async.splitEvery
code

iterable/async/splitEvery

Integer → Iterable<a> → AsyncIterator<[a]>

Yield groups of length n

const { splitEvery } = require('funk-lib/iterable/async');

// AsyncIterator<[0, 1, 2], [3, 4, 5], [6, 7, 8]>
splitEvery(3, from([0, 1, 2, 3, 4, 5, 6, 7, 8]));
iterable.async.sum
code

iterable/async/sum

Iterable<Number> → Promise<Number>

Sum

const { sum } = require('funk-lib/iterable/async');

await sum(from([1, 2, 3])); // 6
iterable.async.sumBy
code

iterable/async/sumBy

(a → Promise<Number>) → Iterable<a> → Promise<Number>

Sum by

const { sumBy } = require('funk-lib/iterable/async');

const iterator = from([{ total: 1 }, { total: 2 }, { total: 3 }]);
// 6
await sumBy(R.prop('total'), iterator);
iterable.async.tail
code

iterable/async/tail

Iterable<a> → AsyncIterator<a>

Yield all but the first item

const { tail } = require('funk-lib/iterable/async');

// AsyncIterator<2, 3, 4, 5>
tail(from(1, 2, 3, 4, 5));
iterable.async.take
code

iterable/async/take

Integer → Iterable<a> → AsyncIterator<a>

Yield only the first n items of an iterable

const { take } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3>
take(3, from(1, 2, 3, 4, 5));
iterable.async.takeWhile
code

iterable/async/takeWhile

(a → Promise<Boolean>) → Iterable<a> → AsyncIterator<a>

Yield items until the predicate returns false

const { takeWhile } = require('funk-lib/iterable/async');

// AsyncIterator<2, 3, 4>
takeWhile(async n => (n < 5), from([2, 3, 4, 5, 6, 1]));
iterable.async.tee
code

iterable/async/tee

Integer → Iterable<a> → [AsyncIterator<a>]

Copy an iterator n times (exhausts its input)

const { tee } = require('funk-lib/iterable/async');

// [AsyncIterator<1, 2, 3>, AsyncIterator<1, 2, 3>, AsyncIterator<1, 2, 3>]
tee(3, from([1, 2, 3]));
iterable.async.times
code

iterable/async/times

Integer → a → AsyncIterator<a>

Yield an item a n times. aka replicate

const { times } = require('funk-lib/iterable/async');

// AsyncIterator<'hi', 'hi', 'hi', 'hi'>
times(4, 'hi');
iterable.async.toArray
code

iterable/async/toArray

Iterable<a> → Promise<[a]>

Transforms an async iterable to an array. exhasts input

const { toArray } = require('funk-lib/iterable/async');

await toArray(from([1, 2, 3])); // [1, 2, 3]
iterable.async.unfold
code

iterable/async/unfold

(a → Promise<[a, a]>) → a → AsyncIterator<a>

Unfold

const { unfold } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 4, 8>
unfold(async n => (n < 10 ? [n, n * 2] : false), 1);
iterable.async.unique
code

iterable/async/unique

Iterable<a> → AsyncIterator<a>

Yield only the unique items in an iterable (by strict equality)

const { unique } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, 3, 4>
unique(from([1, 1, 2, 3, 4, 4, 4]));
iterable.async.uniqueWith
code

iterable/async/uniqueWith

((a, a) → Promise<Boolean>) → Iterable<a> → AsyncIterator<a>

Yield only items that are unique by the predicate

const { uniqueWith } = require('funk-lib/iterable/async');

const records = from([{ id: 1 }, { id: 2 }, { id: 1 }]);
// AsyncIterator<{ id: 1 }, { id: 2 }>
uniqueWith(async (a, b) => (a.id === b.id), records);
iterable.async.unnest
code

iterable/async/unnest

Iterable<Iterable<a>> → AsyncIterator<a>

Flattens one level of a nested iterable of iterables

const { unnest } = require('funk-lib/iterable/async');

// AsyncIterator<1, 2, [3, [4]]>
unnest(from([1, [2, [3, [4]]]]));
iterable.async.unzip
code

iterable/async/unzip

Iterable<[A, B]> → [AsyncIterator<A>, AsyncIterator<B>]

Transforms an iterable of pairs into a pair of AsyncIterator

const { unzip } = require('funk-lib/iterable/async');

// [AsyncIterator<1, 3, 5>, AsyncIterator<2, 4, 6>]
unzip(from([[1, 2], [3, 4], [5, 6]]));
iterable.async.unzipN
code

iterable/async/unzipN

Number → Iterable<[A, B, ...Z]> → [AsyncIterator<A>, AsyncIterator<B>, ...AsyncIterator<Z>]

Transforms an iterable of n-tuple into an n-tuple of async iterators

const { unzipN } = require('funk-lib/iterable/async');

// [AsyncIterator<1, 4, 7>, AsyncIterator<2, 5, 8>, AsyncIterator<3, 6, 9>]
unzipN(3, from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]));
iterable.async.yieldWith
code

iterable/async/yieldWith

(a → Promise<b>) → AsyncIterator<a> → Promise<b>

Create coroutines with custom behavior by transforming yielded values and returning them as the results of the yield. Works with sync iterables

const { yieldWith } = require('funk-lib/iterable/async');

const iterator = (async function*() {
  const one = yield await { val: 1 };
  const two = yield await { val: 2 };
  return one + two;
})();
// 3
await yieldWith(async ({ val }) => val, iterator);
iterable.async.zip
code

iterable/async/zip

Iterable<a> → Iterable<b> → AsyncIterator<[a, b]>

Zips two iterables into pairs of items from corresponding indices of the input iterables. truncated to shorter of two iterables

const { zip } = require('funk-lib/iterable/async');

// AsyncIterator<[1, 4], [2, 5], [3, 6]>
zip(from([1, 2, 3]), from([4, 5, 6]));
iterable.async.zipAll
code

iterable/async/zipAll

[Iterable<a>, Iterable<b>, Iterable<c>] → AsyncIterator<[a, b, c]>

Zip an array of iterables into an async iterator of arrays of items from corresponding indices of the input iterables

const { zipAll } = require('funk-lib/iterable/async');

// AsyncIterator<[1, 4, 7], [2, 5, 8], [3, 6, 9]>
zipAll([
  from([1, 2, 3]),
  from([4, 5, 6]),
  from([7, 8, 9]),
]);
iterable.async.zipAllWith
code

iterable/async/zipAllWith

((...a) → Promise<b>) → [Iterable<a>] → AsyncIterator<b>

Zip multiple async iterators with custom zipping function

const { zipAllWith } = require('funk-lib/iterable/async');

// AsyncIterator<[7, 4, 1], [8, 5, 2], [9, 6, 3]>
zipAllWith(async (a, b, c) => [c, b, a], [
  from([1, 2, 3]),
  from([4, 5, 6]),
  from([7, 8, 9]),
]);
iterable.async.zipWith
code

iterable/async/zipWith

((a, b) → Promise<c>) → Iterable<a> → Iterable<b> → AsyncIterator<c>

Zip two async iterables with a custom zipping function

const { zipWith } = require('funk-lib/iterable/async');

// AsyncIterator<[4, 1], [5, 2], [6, 3]>
zipWith(async (a, b) => [b, a])(from([1, 2, 3]), from([4, 5, 6]));
iterable.async.zipWithN
code

iterable/async/zipWithN

Zip N async iterables with a custom zipping function

const { zipWithN } = require('funk-lib/iterable/async');

// AsyncIterator<[4, 1], [5, 2], [6, 3]>
zipWithN(2)(async (a, b) => [b, a])(
  from([1, 2, 3]),
  from([4, 5, 6]),
);
iterable.sync
code

iterable/sync

Functions for working with sync iterables

const { sync } = require('funk-lib/iterable');
iterable.sync.append
code

iterable/sync/append

a → Iterable<a> → Iterator<a>

Append an item a to the start of an iterable

const { append } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3, 4>
append(4, from([1, 2, 3]));
iterable.sync.concat
code

iterable/sync/concat

Iterable<a> → Iterable<a> → Iterator<a>

Yield all items from one iterator, then the other

const { concat } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3, 4, 5, 6>
concat(from([1, 2, 3]), from([4, 5, 6]));
iterable.sync.correspondsWith
code

iterable/sync/correspondsWith

((a, b) → Boolean) → Iterable<a> → Iterable<b> → Boolean

Check if two iterables match for every index with a custom comparator

const { correspondsWith } = require('funk-lib/iterable/sync');

const one = from([{ id: 1 }, { id: 2 }, { id: 3 }]);
const two = from([{ id: 1 }, { id: 2 }, { id: 3 }]);
// true
correspondsWith(R.prop('id'), one, two);
iterable.sync.count
code

iterable/sync/count

(a → Boolean) → Iterable<a> → Integer

Return the number of items in an iterable. exhasts input

const { count } = require('funk-lib/iterable/sync');

// 4
count(n => (n > 3), from([1, 2, 3, 4, 5, 6, 7]));
iterable.sync.cycle
code

iterable/sync/cycle

Iterable<a> → Iterator<a>

Yield iterable items cyclically, infinitely looping when the input is exhausted

const { cycle } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3, 1, 2, 3, ...>
cycle(from([1, 2, 3]));
iterable.sync.cycleN
code

iterable/sync/cycleN

Integer → Iterable<a> → Iterator<a>

Yield all items from an iterator, n times

const { cycleN } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 1, 2, 1, 2>
cycleN(3, from([1, 2]));
iterable.sync.drop
code

iterable/sync/drop

Integer → Iterable<a> → Iterator<a>

Drop the first n items of an iterable

const { drop } = require('funk-lib/iterable/sync');

// Iterator<4, 5>
drop(3, from(1, 2, 3, 4, 5));
iterable.sync.dropLast
code

iterable/sync/dropLast

Number → Iterable<a> → Iterator<a>

Yield all but the last n items. note: caches n + 1 items

const { dropLast } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3>
dropLast(2, from([1, 2, 3, 4, 5]));
iterable.sync.dropWhile
code

iterable/sync/dropWhile

(a → Boolean) → Iterable<a> → Iterator<a>

Ignore yielded items until the predicate returns false

const { dropWhile } = require('funk-lib/iterable/sync');

// Iterator<5, 6, 1>
dropWhile(n => (n < 5), from([2, 3, 4, 5, 6, 1]));
iterable.sync.enumerate
code

iterable/sync/enumerate

Iterable<a> → Iterator<[Integer, a]>

Transform an iterable to an iterable of pairs of indices and their items

const { enumerate } = require('funk-lib/iterable/sync');

// Iterator<[0, 'zero'], [1, 'one'], [2, 'two']>
enumerate(from(['zero', 'one', 'two']));
iterable.sync.every
code

iterable/sync/every

(a → Boolean) → Iterable<a> → Boolean

Do all items pass their predicate?

const { every } = require('funk-lib/iterable/sync');

// false
every(n => (n < 4), from([1, 2, 3, 4]));
iterable.sync.exhaust
code

iterable/sync/exhaust

Iterable<a> → undefined

Yield all items

const { exhaust } = require('funk-lib/iterable/sync');

const iterator = from([1, 2, 3]);
exhaust(iterator);
toArray(iterator); // []
iterable.sync.filter
code

iterable/sync/filter

(a → Boolean) → Iterable<a> → Iterator<a>

Yield only items that pass the predicate

const { filter } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3, 4>
filter(n => (n < 5), from([1, 2, 3, 4, 5, 6, 7, 8]));
iterable.sync.find
code

iterable/sync/find

(a → Boolean) → Iterable<a> → a|undefined

Find

const { find } = require('funk-lib/iterable/sync');

const records = [{ id: 1 }, { id: 2 }, { id: 3 }];
// { id: 2 }
find(record => (record.id === 2), records);
iterable.sync.findIndex
code

iterable/sync/findIndex

(a → Boolean) → Iterable<a> → Integer

Find index

const { findIndex } = require('funk-lib/iterable/sync');

const records = [{ id: 1 }, { id: 2 }, { id: 3 }];
// 1
find(record => (record.id === 2), records);
iterable.sync.flatIterate
code

iterable/sync/flatIterate

(a → Iterable<a>) → a → Iterator<a>

Flat iterate

const { flatIterate } = require('funk-lib/iterable/sync');

// Iterator<0, 0, 1, 2, 2, 4, 3, 6, 4, 8, ...>
flatIterate(function* (n) {
  yield n;
  yield (n * 2);
  return n + 1;
}, 0));
iterable.sync.flatMap
code

iterable/sync/flatMap

(a → Iterable<b>) → Iterable<a> → Iterator<b>

Maps a function over an iterable and concatenates the results. a.k.a. "chain"

const { flatMap } = require('funk-lib/iterable/sync');

const iterator = from([1, 2, 3]);

// Iterator<1, 2, 2, 4, 3, 6>
flatMap(function* (n) {
  yield n;
  yield n * 2;
}, iterator);
iterable.sync.flatten
code

iterable/sync/flatten

Iterable<Iterable<a>> → Iterator<a>

Flattens a nested iterable of iterables into a single iterable

const { flatten } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3, 4>
unnest(from([1, [2, [3, [4]]]]));
iterable.sync.flattenN
code

iterable/sync/flattenN

Number → Iterable<Iterable<a>> → Iterator<a>

Flattens n-levels of a nested iterable of iterables

const { flattenN } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3, [4]>
flattenN(2, from([1, [2, [3, [4]]]]))
iterable.sync.forEach
code

iterable/sync/forEach

(a → b) → Iterable<a> → Iterator<a>

Run a function (side-effect) once for each item

const { forEach } = require('funk-lib/iterable/sync');

// log 1
// log 2
// log 3
// Iterator<1, 2, 3>
forEach(console.log, from([1, 2, 3]));
iterable.sync.frame
code

iterable/sync/frame

Integer → Iterable<a> → Iterator<[a]>

Yield a sliding "window" of length n. note: caches n items

const { frame } = require('funk-lib/iterable/sync');

// Iterator<[0, 1, 2], [1, 2, 3], [2, 3, 4], [4, 5, 6]>
frame(3, from([0, 1, 2, 3, 4, 5, 6]));
iterable.sync.from
code

iterable/sync/from

Iterable<a> → Iterator<a>

Returns an iterator from an iterable

const { from } = require('funk-lib/iterable/sync');

from([1, 2, 3]); // Iterator<1, 2, 3>
iterable.sync.group
code

iterable/sync/group

Iterable<a> → Iterator<[a]>

Yield groups of items where the adjacent items are strictly equal

const { group } = require('funk-lib/iterable/sync');

// Iterator<[1, 1, 1], [2, 2], [3]>
group(from([1, 1, 1, 2, 2, 3]));
iterable.sync.groupWith
code

iterable/sync/groupWith

((a, a) → Boolean) → Iterable<a> → Iterator<[a]>

Yield groups of items where the predicate returns truthy for adjacent items

const { groupWith } = require('funk-lib/iterable/sync');

// Iterator<[1, 1, 1], [2, 2], [3]>
groupWith(n => n, from([1, 1, 1, 2, 2, 3]));
iterable.sync.indices
code

iterable/sync/indices

Iterable<a> → Iterator<Integer>

Get an iterator of indices (0 to length - 1)

const { indices } = require('funk-lib/iterable/sync');

// Iterator<0, 1, 2>
indices(from(['a', 'b', 'c']));
iterable.sync.init
code

iterable/sync/init

Iterable<a> → Iterator<a>

Yield all but the last 1 item

const { init } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3, 4>
init(from([1, 2, 3, 4, 5]));
iterable.sync.intersperse
code

iterable/sync/intersperse

a → Iterable<a> → Iterator<a>

Insert an item a between every item in the iterable

const { intersperse } = require('funk-lib/iterable/sync');

// Iterator<'a', '-', 'b', '-', 'c'>
intersperse('-', from('a', 'b', 'c'));
iterable.sync.isEmpty
code

iterable/sync/isEmpty

Iterable<a> → Boolean

Is an iterable empty? (done or length = 0)

const { isEmpty } = require('funk-lib/iterable/sync');

isEmpty(from([])); // true
isEmpty(from([1])); // false
iterable.sync.iterate
code

iterable/sync/iterate

(a → a) → a → Iterator<a>

Iterate infinitely, yielding items from seed through a predicate

const { iterate } = require('funk-lib/iterable/sync');

// Iterator<0, 2, 4, 6, 8, 10, ...>
iterate(n => n + 2, 0);
iterable.sync.join
code

iterable/sync/join

Iterable<a> → String

Serialize iterator items to a string

const { join } = require('funk-lib/iterable/sync');

// 'abcde'
join(from(['a', 'b', 'c', 'd', 'e']));
iterable.sync.joinWith
code

iterable/sync/joinWith

String → Iterable<a> → String

Serialize iterator items to a string with an arbitrary spacer

const { joinWith } = require('funk-lib/iterable/sync');

// 'some-slug-parts';
joinWith('-', from(['some', 'slug', 'parts']));
iterable.sync.last
code

iterable/sync/last

Iterable<a> → a

Returns the last item

const { last } = require('funk-lib/iterable/sync');

last(from(1, 2, 3)); // 3
iterable.sync.length
code

iterable/sync/length

Iterable<a> → Integer

Get length of iterable

const { length } = require('funk-lib/iterable/sync');

// 5
length(from([1, 2, 3, 4, 5]));
iterable.sync.map
code

iterable/sync/map

(a → b) → Iterable<a> → Iterator<b>

Applies a function to each of an iterable's yielded items

const { map } = require('funk-lib/iterable/sync');

// Iterator<2, 4, 6>
map(n => n * 2, from([1, 2, 3]));
iterable.sync.max
code

iterable/sync/max

Iterable<Number> → Number

Max

const { max } = require('funk-lib/iterable/sync');

max(from([1, 2, 3])); // 3
iterable.sync.maxBy
code

iterable/sync/maxBy

(a → Number) → Iterable<a> → Number

Max by

const { maxBy } = require('funk-lib/iterable/sync');

const iterator = from([{ total: 1 }, { total: 2 }, { total: 3 }]);
// 3
maxBy(R.prop('total'), iterator);
iterable.sync.min
code

iterable/sync/min

Iterable<Number> → Number

Min

const { min } = require('funk-lib/iterable/sync');

min(from([1, 2, 3])); // 1
iterable.sync.minBy
code

iterable/sync/minBy

(a → Number) → Iterable<a> → Number

Min by

const { minBy } = require('funk-lib/iterable/sync');

const iterator = from([{ total: 1 }, { total: 2 }, { total: 3 }]);
// 1
minBy(R.prop('total'), iterator);
iterable.sync.next
code

iterable/sync/next

Iterable<a> → a

Returns the first or "next" item. aka head

const { next } = require('funk-lib/iterable/sync');

next(from([1, 2, 3])); // 1
next(from([])); // StopIterationError()
iterable.sync.nextOr
code

iterable/sync/nextOr

a → Iterable<a> → a

Return the next item, or a default value if iterable is empty

const { nextOr } = require('funk-lib/iterable/sync');

nextOr(10, from([1, 2, 3])); // 1
nextOr(10, from([])); // 10
iterable.sync.none
code

iterable/sync/none

(a → Boolean) → Iterable<a> → Boolean

Do all items fail the predicate?

const { none } = require('funk-lib/iterable/sync');

// true
none(n => (n > 5), from([1, 2, 3, 4, 5]));
iterable.sync.nth
code

iterable/sync/nth

Integer → Iterable<a> → a|undefined

Returns the element at the nth index

const { nth } = require('funk-lib/iterable/sync');

// 'b'
nth(1, from(['a', 'b', 'c', 'd']));
iterable.sync.of
code

iterable/sync/of

...a → Iterator<a>

Create an iterator of one or more (variadic) arguments

const { of } = require('funk-lib/iterable/sync');

of(1, 2, 3); // Iterator<1, 2, 3>
iterable.sync.pad
code

iterable/sync/pad

a → Iterable<a> → Iterator<a>

Pad iterable with an infinite number of items a

const { pad } = require('funk-lib/iterable/sync');

// Iterator<'a', 'b', 'c', 'd', 'd', 'd', ...>
pad('d', from(['a', 'b', 'c']));
iterable.sync.padTo
code

iterable/sync/padTo

Integer → a → Iterable<a> → Iterator<a>

Pad an iterable with with a finite number of items a

const { padTo } = require('funk-lib/iterable/sync');

// Iterator<'a', 'b', 'c', 'd', 'd', 'd'>
padTo(6, 'd', from(['a', 'b', 'c']));
iterable.sync.partition
code

iterable/sync/partition

(a → Boolean) → Iterable<a> → [Iterator<a>, Iterator<a>]

Split an iterable into a pair of iterables based on the truthiness of their predicate

const { partition } = require('funk-lib/iterable/sync');

// [Iterator<0, 1, 2>, Iterator<3, 4, 5, 6>]
partition(n => n < 3, from([0, 1, 2, 3, 4, 5, 6]));
iterable.sync.prepend
code

iterable/sync/prepend

a → Iterable<a> → Iterator<a>

Prepend an item a to the end of an iterable

const { prepend } = require('funk-lib/iterable/sync');

// Iterator<0, 1, 2, 3>
prepend(0, from([1, 2, 3]));
iterable.sync.range
code

iterable/sync/range

Number → Number → Iterator<Number>

Iterates from 0 to n - 1 (exclusive)

const { range } = require('funk-lib/iterable/sync');

range(0, 5); // Iterator<0, 1, 2, 3, 4>
iterable.sync.rangeStep
code

iterable/sync/rangeStep

Number → Number → Number → Iterator<Number>

Iterates from 0 to n by with a step (exclusive)

const { rangeStep } = require('funk-lib/iterable/sync');

// Iterator<0, 15, 30, 45, 60, 75, 90>
rangeStep(15, 0, 100);
iterable.sync.reduce
code

iterable/sync/reduce

((a, b) → a) → a → Iterable<b> → a

Reduce

const { reduce } = require('funk-lib/iterable/sync');

// 6
reduce((a, b) => a + b, 0, from([1, 2, 3]));
iterable.sync.reject
code

iterable/sync/reject

(a → Boolean) → Iterable<a> → Iterator<a>

Yield only items that do not pass the predicate

const { reject } = require('funk-lib/iterable/sync');

// Iterator<6, 7, 8>
reject(n => (n < 5), from(1, 2, 3, 4, 5, 6, 7, 8));
iterable.sync.repeat
code

iterable/sync/repeat

a → Iterator<a>

Infinitely yield an item (a)

const { repeat } = require('funk-lib/iterable/sync');

// Iterator<'hi', 'hi', 'hi', ...>
repeat('hi');
iterable.sync.reverse
code

iterable/sync/reverse

Iterable<a> → Iterator<a>

Reverse

const { reverse } = require('funk-lib/iterable/sync');

reverse(from([1, 2, 3])); // Iterator<3, 2, 1>
iterable.sync.scan
code

iterable/sync/scan

((a, b) → a) → a → Iterable<b> → Iterator<a>

Scan

const { scan } = require('funk-lib/iterable/sync');

// Iterator<1, 1, 2, 6, 24>
scan(R.multiply, 1, from([1, 2, 3, 4]));
iterable.sync.slice
code

iterable/sync/slice

Integer → Integer → Iterable<a> → Iterator<a>

Slice an iterator between two indices

const { slice } = require('funk-lib/iterable/sync');

// Iterator<3, 4, 5>
slice(2, 5, from([1, 2, 3, 4, 5, 6, 7, 8]));
iterable.sync.sort
code

iterable/sync/sort

((a, a) → Number) → Iterable<a> → Iterator<a>

Sort

const { sort } = require('funk-lib/iterable/sync');

// Iterator<'c', 'b', 'a'>
sort((a, b) => b.localeCompare(a), from(['a', 'b', 'c']));
iterable.sync.splitAt
code

iterable/sync/splitAt

Integer → Iterable<a> → [Iterator<a>, Iterator<a>]

Split an iterable into a pair of iterables at a particular index

const { splitAt } = require('funk-lib/iterable/sync');

// [Iterator<0, 1, 2, 3, 4>, Iterator<5, 6>]
splitAt(4, from([0, 1, 2, 3, 4, 5, 6]));
iterable.sync.splitEvery
code

iterable/sync/splitEvery

Integer → Iterable<a> → Iterator<[a]>

Yield groups of length n

const { splitEvery } = require('funk-lib/iterable/sync');

// Iterator<[0, 1, 2], [3, 4, 5], [6, 7, 8]>
splitEvery(3, from([0, 1, 2, 3, 4, 5, 6, 7, 8]));
iterable.sync.sum
code

iterable/sync/sum

Iterable<Number> → Number

Sum

const { sum } = require('funk-lib/iterable/sync');

sum(from([1, 2, 3])); // 6
iterable.sync.sumBy
code

iterable/sync/sumBy

(a → Number) → Iterable<a> → Number

Sum by

const { sumBy } = require('funk-lib/iterable/sync');

const iterator = from([{ total: 1 }, { total: 2 }, { total: 3 }]);
// 6
sumBy(R.prop('total'), iterator);
iterable.sync.tail
code

iterable/sync/tail

Iterable<a> → Iterator<a>

Yield all but the first item

const { tail } = require('funk-lib/iterable/sync');

// Iterator<2, 3, 4, 5>
tail(from(1, 2, 3, 4, 5));
iterable.sync.take
code

iterable/sync/take

Integer → Iterable<a> → Iterator<a>

Yield only the first n items of an iterable

const { take } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3>
take(3, from(1, 2, 3, 4, 5));
iterable.sync.takeWhile
code

iterable/sync/takeWhile

(a → Boolean) → Iterable<a> → Iterator<a>

Take while

const { takeWhile } = require('funk-lib/iterable/sync');

// Iterator<2, 3, 4>
takeWhile(n => (n < 5), from([2, 3, 4, 5, 6, 1]));
iterable.sync.tee
code

iterable/sync/tee

Integer → Iterable<a> → [Iterator<a>]

Copy an iterator n times (exhausts its input)

const { tee } = require('funk-lib/iterable/sync');

// [Iterator<1, 2, 3>, Iterator<1, 2, 3>, Iterator<1, 2, 3>]
tee(3, from([1, 2, 3]));
iterable.sync.times
code

iterable/sync/times

Integer → a → Iterator<a>

Yield an item a n times. aka replicate

const { times } = require('funk-lib/iterable/sync');

// Iterator<'hi', 'hi', 'hi', 'hi'>
times(4, 'hi');
iterable.sync.toArray
code

iterable/sync/toArray

Iterable<a> → [a]

Transforms an iterable to an array. exhasts input

const { toArray } = require('funk-lib/iterable/sync');

toArray(from([1, 2, 3])); // [1, 2, 3]
iterable.sync.unfold
code

iterable/sync/unfold

(a → [a, a]) → a → Iterator<a>

Unfold

const { unfold } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 4, 8>
unfold(n => (n < 10 ? [n, n * 2] : false), 1);
iterable.sync.unique
code

iterable/sync/unique

Iterable<a> → Iterator<a>

Yield only the unique items in an async iterable (by strict equality)

const { unique } = require('funk-lib/iterable/sync');

// Iterator<1, 2, 3, 4>
unique(from([1, 1, 2, 3, 4, 4, 4]));
iterable.sync.uniqueWith
code

iterable/sync/uniqueWith

((a, a) → Boolean) → Iterable<a> → Iterator<a>

Yield only items that are unique by the predicate

const { uniqueWith } = require('funk-lib/iterable/sync');

const records = from([{ id: 1 }, { id: 2 }, { id: 1 }]);
// Iterator<{ id: 1 }, { id: 2 }>
uniqueWith((a, b) => (a.id === b.id), records);
iterable.sync.unnest
code

iterable/sync/unnest

Iterable<Iterable<a>> → Iterator<a>

Flattens one level of a nested iterable of iterables

const { unnest } = require('funk-lib/iterable/sync');

// Iterator<1, 2, [3, [4]]>
unnest(from([1, [2, [3, [4]]]]));
iterable.sync.unzip
code

iterable/sync/unzip

Iterable<[A, B]> → [Iterator<A>, Iterator<B>]

Transforms an iterable of pairs into a pair of iterators

const { unzip } = require('funk-lib/iterable/sync');

// [Iterator<1, 3, 5>, Iterator<2, 4, 6>]
unzip(from([[1, 2], [3, 4], [5, 6]]));
iterable.sync.unzipN
code

iterable/sync/unzipN

Number → Iterable<[A, B, ...Z]> → [Iterator<A>, Iterator<B>, ...Iterator<Z>]

Transforms an iterable of n-tuple into an n-tuple of iterators

const { unzipN } = require('funk-lib/iterable/sync');

// [AsyncIterator<1, 4, 7>, AsyncIterator<2, 5, 8>, AsyncIterator<3, 6, 9>]
unzipN(3, from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]));
iterable.sync.yieldWith
code

iterable/sync/yieldWith

(a → b) → Iterator<a> → b

Create coroutines with custom behavior by transforming yielded values and returning them as the results of the yield

const { yieldWith } = require('funk-lib/iterable/sync');

const iterator = (function*() {
  const one = yield { val: 1 };
  const two = yield { val: 2 };
  return one + two;
})();
// 3
yieldWith(({ val }) => val, iterator);
iterable.sync.zip
code

iterable/sync/zip

Iterable<a> → Iterable<b> → Iterator<[a, b]>

Zips two iterables into pairs of items from corresponding indices of the input iterables. truncated to shorter of two iterables

const { zip } = require('funk-lib/iterable/sync');

// Iterator<[1, 4], [2, 5], [3, 6]>
zip(from([1, 2, 3]), from([4, 5, 6]));
iterable.sync.zipAll
code

iterable/sync/zipAll

[Iterable<a>, Iterable<b>, Iterable<c>] → Iterator<[a, b, c]>

Zip an array of iterables into an async iterator of arrays of items from corresponding indices of the input iterables

const { zipAll } = require('funk-lib/iterable/sync');

// Iterator<[1, 4, 7], [2, 5, 8], [3, 6, 9]>
zipAll([
  from([1, 2, 3]),
  from([4, 5, 6]),
  from([7, 8, 9]),
]);
iterable.sync.zipAllWith
code

iterable/sync/zipAllWith

((...a) → Promise<b>) → [Iterable<a>] → Iterator<b>

Zip multiple iterators with custom zipping function

const { zipAllWith } = require('funk-lib/iterable/sync');

// Iterator<[7, 4, 1], [8, 5, 2], [9, 6, 3]>
zipAllWith((a, b, c) => [c, b, a], [
  from([1, 2, 3]),
  from([4, 5, 6]),
  from([7, 8, 9]),
]);
iterable.sync.zipWith
code

iterable/sync/zipWith

((a, b) → Promise<c>) → Iterable<a> → Iterable<b> → Iterator<c>

Zip two iterables with a custom zipping function

const { zipWith } = require('funk-lib/iterable/sync');

// Iterator<[4, 1], [5, 2], [6, 3]>
zipWith((a, b) => [b, a])(from([1, 2, 3]), from([4, 5, 6]));
iterable.sync.zipWithN
code

iterable/sync/zipWithN

Zip N iterables with a custom zipping function

const { zipWithN } = require('funk-lib/iterable/sync');

// Iterator<[4, 1], [5, 2], [6, 3]>
zipWithN(2)((a, b) => [b, a])(
  from([1, 2, 3]),
  from([4, 5, 6]),
);
number
code

number

Functions for working with Number

const { number } = require('funk-lib');
number.random
code

number/random

Number → Number → Integer

Get a random integer between two inclusive bounds

const { random } = require('funk-lib/number');

random(0, 100); // 42
number.randomFloat
code

number/randomFloat

Number → Number → Float

Get a random float between two inclusive bounds

const { randomFloat } = require('funk-lib/number');

randomFloat(0, 100); // 42.38076848431584
object
code

object

Functions for working with Object

const { object } = require('funk-lib');
object.clear
code

object/clear

{a} → {}

Delete all object properties. mutating + identity

const { clear } = require('funk-lib/object');

const obj = { a: 1, b: 2 };
clear(obj); // obj === {}
object.deepFreeze
code

object/deepFreeze

{*} → {*}

Recursive freeze a nested object. mutating + identity

const { deepFreeze } = require('funk-lib/object');

const obj = { a: 1 };
deepFreeze(obj); // { a: 1 }
obj.a = 2; // TypeError
object.del
code

object/del

String → {a} → {a}

Delete an object property. mutating + identity

const { del } = require('funk-lib/object');

const obj = { a: 1, b: 2 };
del('a', obj); // obj === { b: 2 }
object.firstKey
code

object/firstKey

{ k: v } → k

Get an object's first key

const { firstKey } = require('funk-lib/object');

firstKey({ a: 1 }); // 'a'
object.firstPair
code

object/firstPair

{ k: v } → [k, v]

Get an object's first key: value pair

const { firstPair } = require('funk-lib/object');

firstPair({ a: 1 }); // ['a', 1]
object.firstValue
code

object/firstValue

{ k: v } → v

Get an object's first value

const { firstValue } = require('funk-lib/object');

firstValue({ a: 1 }); // 1
object.flattenWith
code

object/flattenWith

((k, k) → l) → { k: v } → { l: v }

Flatten a deeply nested object, joining keys with with a binary function. Inverse of object/nestWith

const { flattenWith } = require('funk-lib/object');

// { 'src/one': 1, 'src/two/three': 3 }
flattenWith(R.unapply(R.join('/')), { src: { one: 1, two: { three: 3 } } });
object.isEmpty
code

object/isEmpty

{a} -> Boolean

Is an object empty?

const { isEmpty } = require('funk-lib/object');

isEmpty({}); // true
object.mapDeep
code

object/mapDeep

(a → b) → { k: a } → { k: b }

Recursively map a deep object's leaf nodes

const { mapDeep } = require('funk-lib/object');

// { a: { b: 2, c: { d: 3 } } }
mapDeep(n => (n + 1), { a: { b: 1, c: { d: 2 } } });
object.mapKeys
code

object/mapKeys

(k → k) → { k: v } → { k: v }

Map object keys

const { mapKeys } = require('funk-lib/object');

mapKeys(R.reverse, { one: 1, two: 2 }); // { eno: 1, owt: 2 }
object.mapPairs
code

object/mapPairs

([a, b] → [c, d]) → { a: b } → { c: d }

Map object key / value pairs

const { mapPairs } = require('funk-lib/object');

mapPairs(R.reverse, { a: 1, b: 2 }); // { 1: 'a', 2: 'b' }
object.nestWith
code

object/nestWith

(k → [l]) → { k: v } → { l: v }

Deeply nest a flattened object, splitting keys with a unary function. Inverse of object/flattenWith

const { nestWith } = require('funk-lib/object');

// { src: { one: 1, two: { three: 3 } } }
nestWith(R.split('/'), { 'src/one': 1, 'src/two/three': 3 });
object.pickAs
code

object/pickAs

{ k: w } → { k: v } → { w: v }

Pick and rename object keys in a single operation

const { pickAs } = require('funk-lib/object');

// { b: 1, c: 2 }
pickAs({ a: 'b', b: 'c' }, { a: 1, b: 2 });
object.toHumanJSON
code

object/toHumanJSON

JSON → String

Serialize to JSON with newlines and 2-space indentation

const { toHumanJSON } = require('funk-lib/object');

// '{
//   "one": {
//     "two": 2
//   }
// }'
toHumanJSON({ one: { two: 2 } });
process
code

process

Functions for working with Process

const { process } = require('funk-lib');
process.onSigInt
const { onSigInt } = require('funk-lib/process');

const offSigInt = onSigInt(_ => {
 console.log('SIGINT');
 offSigInt(); // unsubscribe
});
stream
code

stream

Functions for working with Stream

const { stream } = require('funk-lib');
stream.from
code

stream/from

Iterable → Stream

Readable stream from iterable

const { from } = require('funk-lib/stream');

from([1, 2, 3]); // ReadableStream<1, 2, 3>
stream.fromString
code

stream/fromString

String → Stream

String to stream

const { fromString } = require('funk-lib/stream');

fromString('hello'); // ReadableStream<'hello'>
stream.toString
code

stream/toString

Stream → String

Stream to string

const { toString } = require('funk-lib/stream');

await toString(from(['a', 'b', 'c'])); // 'abc'
string
code

string

Functions for working with String

const { string } = require('funk-lib');
string.capitalize
code

string/capitalize

String → String

Capitalize the first letter of a string

const { capitalize } = require('funk-lib/string');

capitalize('hello'); // 'Hello'
string.escapeRegExpStr
code

string/escapeRegExpStr

String → String

Escape a string for use with the RegExp constructor

const { escapeRegExpStr } = require('funk-lib/string');

const rx = '^a';
new RegExp(escapeRegExpStr(rx)).test('a'); // false
new RegExp(rx).test('a'); // true
string.localeCompare
code

string/localeCompare

String → String → Number

Locale compare

const { localeCompare } = require('funk-lib/string');

localeCompare('b', 'a'); // -1
string.parseBase64
code

string/parseBase64

String → String

Decode a string from base64

const { parseBase64 } = require('funk-lib/string');

parseBase64('aGVsbG8='); // 'hello'
string.slugify
code

string/slugify

String → String

Slugify a string

const { slugify } = require('funk-lib/string');

slugify('Hello World!'); // 'hello-world'
string.template
code

string/template

String → {*} → String

String interpolation. Reasonably similar to JavaScript template literals.

const { template } = require('funk-lib/string');

// 'Hello Pat!'
template('Hello ${ name }!', { name: 'Pat' });
string.toBase64
code

string/toBase64

String → String

Encode a string to base64

const { toBase64 } = require('funk-lib/string');

toBase64('hello'); // 'aGVsbG8='
url
code

url

Functions for working with urls, and querystrings

const { url } = require('funk-lib');
url.isDataUrl
code

url/isDataUrl

a → Boolean

Is a string a data url

const { isDataUrl } = require('funk-lib/url');

isDataUrl('data:,Hello%2C%20World!'); // true
isDataUrl('https://foo.bar'); // false
url.parseDataUrl
code

url/parseDataUrl

String → { mediatype, data, base64 }

Parse a data url into its parts

const { parseDataUrl } = require('funk-lib/url');

// {
//   base64: true,
//   data: 'eyJ0ZXN0IjoidGV4dCJ9',
//   mediatype: 'application/json',
// }
parseDataUrl('data:application/json;base64,eyJ0ZXN0IjoidGV4dCJ9');
uuid
code

uuid

Functions for working with UUIDs

const { uuid } = require('funk-lib');
uuid.isUuid
code

uuid/isUuid

a → Boolean

Is UUID v4?

const { isUuid } = require('funk-lib/uuid');

isUuid('c4f2e775-a5f9-4796-bd31-46e544bfab06'); // true
uuid.uuid
code

uuid/uuid

a → String

Random UUID v4

const { uuid } = require('funk-lib/uuid');

uuid(); // 'c4f2e775-a5f9-4796-bd31-46e544bfab06'