UNPKG

extra-function

Version:

Functions are one of the fundamental building blocks in JavaScript.

793 lines (792 loc) 20.3 kB
/** * unknown function type. * @params args arguments * @returns unknown value */ export type Function = (...args: unknown[]) => unknown; /** * Do nothing. * @param _args arguments (ignored) * @example * ```javascript * xfunction.NOOP(1, 2); * // → undefined * * xfunction.NOOP('a', 'b'); * // → undefined * ``` */ export declare function NOOP(..._args: unknown[]): void; /** * Return false. * @param _args arguments (ignored) * @returns false. * @example * ```javascript * xfunction.FALSE(); * // → false * ``` */ export declare function FALSE(..._args: unknown[]): false; /** * Return true. * @param _args arguments (ignored) * @returns true. * @example * ```javascript * xfunction.TRUE(); * // → true * ``` */ export declare function TRUE(..._args: unknown[]): true; /** * Return the same (first) value. * @param v a value * @returns v * @example * ```javascript * xfunction.IDENTITY(1); * // → 1 * * xfunction.IDENTITY('a'); * // → 'a' * ``` */ export declare function IDENTITY<T>(v: T): T; /** * Compare two values. * @param a a value * @param b another value * @returns a<b: -1, a=b: 0, a>b: 1 * @example * ```javascript * xfunction.COMPARE(1, 2); * // → -1 * * xfunction.COMPARE(2, 1); * // → 1 * * xfunction.COMPARE(1, 1); * // → 0 */ export declare function COMPARE<T>(a: T, b: T): number; /** * Return the arguments passed as a array. * @param args arguments * @returns [...args] * @example * ```javascript * xfunction.ARGUMENTS(1, 2); * // → [1, 2] * * xfunction.ARGUMENTS('a', 'b'); * // → ['a', 'b'] * ``` */ export declare function ARGUMENTS(...args: unknown[]): unknown[]; /** * Get the name of a function. * @param x a function * @returns name * @example * ```javascript * import {delay, debounce} from "jsr:@nodef/extra-function"; * * xfunction.name(delay); * // → 'delay' * * xfunction.name(debounce); * // → 'debounce' * ``` */ export declare function name(x: Function): string; /** * Get the number of parameters of a function. * @param x a function * @returns |[p, q, ...]| | x(p, q, ...) * @example * ```javascript * xfunction.length(() => 0); * // → 0 * * xfunction.length((x, y) => 0); * // → 2 * ``` */ export declare function length(x: Function): number; export { length as arity }; /** * Bind this-object, and optional prefix arguments to a function. * @param x a function * @param ths this object to bind * @param prefix prefix arguments * @returns (...args) => this.x(...prefix, ...args) * @example * ```javascript * var array = [1]; * var fn = xfunction.bind(Array.prototype.push, array); * fn(2, 3, 4); // push(2, 3, 4) * array; * // → [1, 2, 3, 4] * * var array = [1, 2, 3, 4]; * var fn = xfunction.bind(Array.prototype.splice, array, 1); * fn(2); // splice(1, 2) * array; * // → [1, 4] * ``` */ export declare function bind(x: Function, ths: unknown, ...prefix: unknown[]): Function; /** * Invoke a function with specified this-object, and arguments provided individually. * @param x a function * @param ths this object to invoke with * @param args arguments * @returns this.x(...args) * @example * ```javascript * var array = [1]; * xfunction.call(Array.prototype.push, array, 2, 3, 4); // push(2, 3, 4) * array; * // → [1, 2, 3, 4] * * var array = [1, 2, 3, 4]; * xfunction.call(Array.prototype.splice, array, 1, 2); // splice(1, 2) * array; * // → [1, 4] * ``` */ export declare function call(x: Function, ths?: unknown, ...args: unknown[]): unknown; /** * Invoke a function with specified this-object, and arguments provided as an array. * @param x a function * @param ths this object to invoke with * @param args arguments array * @returns this.x(...args) * @example * ```javascript * var array = [1]; * xfunction.apply(Array.prototype.push, array, [2, 3, 4]); // push(2, 3, 4) * array; * // → [1, 2, 3, 4] * * var array = [1, 2, 3, 4]; * xfunction.apply(Array.prototype.splice, array, [1, 2]); // splice(1, 2) * array; * // → [1, 4] * ``` */ export declare function apply(x: Function, ths: unknown | undefined, args: unknown[]): unknown; /** * Check if value is a function. * @param v a value * @returns is function? * @example * ```javascript * xfunction.is(Object.keys); * // → true * * xfunction.is(() => 0); * // → true * * xfunction.is(async () => 0); * // → true * * xfunction.is(0); * // → false * ``` */ export declare function is(v: unknown): v is Function; /** * Check if value is an async function. * @param v a value * @returns is async function? * @example * ```javascript * xfunction.isAsync(async () => 0); * // → true * * xfunction.isAsync(() => 0); * // → false * ``` */ export declare function isAsync(v: unknown): boolean; /** * Check if value is a generator function. * @param v a value * @returns is generator function? * @example * ```javascript * function* naturalNumbers() { * for (var i=0;; ++i) * yield i; * } * * xfunction.isGenerator(naturalNumbers); * // → true * * xfunction.isGenerator(() => 0); * // → false * ``` */ export declare function isGenerator(v: unknown): v is GeneratorFunction; /** * Contextify a function by accepting the first parameter as this-object. * @param x a function * @returns (...args) => x(this, ...args) * @example * ```javascript * function count(x, value) { * var a = 0; * for (var v of x) * if (v===value) ++a; * return a; * } * * var fn = xfunction.contextify(count); * * fn.call([6, 3, 4, 3], 3); * // → 2 * * fn.call([6, 1, 4, 3], 3); * // → 1 * ``` */ export declare function contextify(x: Function): Function; /** * Decontextify a function by accepting this-object as the first argument. * @param x a function * @returns (this, ...args) => this.x(...args) * @example * ```javascript * function count(value) { * var a = 0; * for (var v of this) * if (v===value) ++a; * return a; * } * * var fn = xfunction.decontextify(count); * * fn([6, 3, 4, 3], 3); * // → 2 * * fn([6, 1, 4, 3], 3); * // → 1 * ``` */ export declare function decontextify(x: Function): Function; /** * Generate a result-negated version of a function. * @param x a function * @returns (...args) => !x(...args) * @example * ```javascript * var fn = xfunction.negate(isFinite); * fn(Infinity) * // → true * fn(1) * // → false * * var fn = xfunction.negate(isNaN); * fn(1); * // → true * fn(NaN); * // → false * ``` */ export declare function negate(x: Function): Function; /** * Resolve arguments into a unique key. * @param args arguments * @returns unique key */ export type Resolver = (...args: unknown[]) => unknown; /** * Generate result-cached version of a function. * @param x a function * @param fr resolver ((...args) => unique key) [IDENTITY] * @param cache result cache [Map()] * @example * ```javascript * var calls = 0; * * function factorialRec(n: number) { * if (n<=1) return 1; * return n * factorialRec(n-1); * } * * function factorial(n: number) { * ++calls; * return factorialRec(n); * } * * var fn = xfunction.memoize(factorial); * fn(3); * // → 6 * fn(4); * // → 24 * fn(5); * // → 120 * fn(3); * // → 6 * fn(4); * // → 24 * fn(5); * // → 120 * calls; * // → 3 * * * var calls = 0; * * function hypot(x: number, y: number) { * ++calls; * return Math.hypot(x, y); * } * * function resolver(x: number, y: number) { * return 4093*y + x; // a hash * } * * var fn = xfunction.memoize(hypot, resolver); * fn(3, 4); * // → 5 * fn(6, 8); * // → 10 * fn(5, 12); * // → 13 * fn(3, 4); * // → 5 * fn(6, 8); * // → 10 * fn(5, 12); * // → 13 * calls; * // → 3 * ``` */ export declare function memoize(x: Function, fr?: Resolver | null, cache?: Map<unknown, unknown> | null): Function; /** * Generate a parameter-reversed version of a function. * @param x a function * @returns (p, q, ...) => x(..., q, p) * @example * ```javascript * function divide(x, y) { * return x/y; * } * * var fn = xfunction.reverse(divide); * fn(2, 4); * // → 2 * fn(2, 6); * // → 3 * fn(2, 8); * // → 4 * * * var array = [1]; * * function push(...args) { * array.push(...args); * } * * var fn = xfunction.reverse(push); * fn(2, 3, 4); // push(2, 3, 4) in reverse order * array; * // → [1, 4, 3, 2] * ``` */ export declare function reverse(x: Function): Function; export { reverse as flip }; /** * Generate a (first) parameter-spreaded version of a function. * @param x a function * @returns (p, q, ...) => x([p, q, ...]) * @example * ```javascript * function sum(x: number[]) { * var a = 0; * for (var v of x) * a += v; * return a; * } * * var fn = xfunction.spread(sum); * fn(1, 2, 3); // sum([1, 2, 3]) * // → 6 * * * var array = [1]; * * function concat(x: number[]) { * return array.concat(x); * } * * var fn = xfunction.spread(concat); * fn(2, 3, 4); // concat([2, 3, 4]) * // → [1, 2, 3, 4] * ``` */ export declare function spread(x: Function): Function; /** * Generate a (first) parameter-collapsed version of a function. * @param x a function * @returns ([p, q, ...]) => x(p, q, ...) * @example * ```javascript * var fn = xfunction.unspread(Math.min); * fn([7, 4, 9]); // Math.min(7, 4, 9) * // → 4 * * var fn = xfunction.unspread((x, i, I) => x.slice(i, I)); * fn([[1, 2, 3, 4], 2]); // [1, 2, 3, 4].slice(2) * // → [3, 4] * ``` */ export declare function unspread(x: Function): Function; /** * Attach prefix arguments to leftmost parameters of a function. * @param x a function * @param prefix prefix arguments * @returns (...args) => x(...prefix, ...args) * @example * ```javascript * var fn = xfunction.attach(Math.min, 100); * fn(180, 130); // Math.min(100, 180, 130) * // → 100 * * var array = [1]; * var fn = xfunction.attach((...vs) => array.push(...vs), 10, 10); * fn(1, 2, 3); // array.push(10, 10, 1, 2, 3) * array; * // → [1, 10, 10, 1, 2, 3] * ``` */ export declare function attach(x: Function, ...prefix: unknown[]): Function; export { attach as partial }; /** * Attach suffix arguments to rightmost parameters of a function. * @param x a function * @param suffix suffix arguments * @returns (...args) => x(...args, ...suffix) * @example * ```javascript * var fn = xfunction.attachRight(Math.min, 100); * fn(180, 130); // Math.min(180, 130, 100) * // → 100 * * var array = [1]; * var fn = xfunction.attachRight((...vs) => array.push(...vs), 10, 10); * fn(1, 2, 3); // array.push(1, 2, 3, 10, 10) * array; * // → [1, 1, 2, 3, 10, 10] * ``` */ export declare function attachRight(x: Function, ...suffix: unknown[]): Function; export { attachRight as partialRight }; /** * Compose functions together, in applicative order. * @param xs functions (f, g) * @returns (f o g), or f(g(x)) * @example * ```javascript * var fn = xfunction.compose(Math.sqrt, Math.abs); * fn(-64); // Math.sqrt(Math.abs(-64)) * // → 8 * * var fn = xfunction.compose(Math.sqrt, Math.min); * fn(22, 9); // Math.sqrt(Math.min(22, 9)) * // → 3 * ``` */ export declare function compose(...xs: Function[]): Function; /** * Compose functions together, such that result is piped forward. * @param xs functions (f, g) * @returns (f ▷ g), or g(f(x)) * @example * ```javascript * var fn = xfunction.composeRight(Math.abs, Math.sqrt); * fn(-64); // Math.sqrt(Math.abs(-64)) * // → 8 * * var fn = xfunction.composeRight(Math.min, Math.sqrt); * fn(22, 9); // Math.sqrt(Math.min(22, 9)) * // → 3 * ``` */ export declare function composeRight(...xs: Function[]): Function; /** * Generate curried version of a function. * @param x a function * @param n number of parameters [all] * @returns (p)(q)(...) => x(p, q, ...) * @example * ```javascript * var sub = (x: number, y: number) => x - y; * var fn = xfunction.curry(sub); * fn(2)(3); // sub(2, 3) * // → -1 * * var fn = xfunction.curry(Math.min, 3); * fn(5)(8)(3); // Math.min(5, 8, 3) * // → 3 * ``` */ export declare function curry(x: Function, n?: number): Function; /** * Generate right-curried version of a function. * @param x a function * @param n number of parameters [all] * @returns (p)(q)(...) => x(..., q, p) * @example * ```javascript * var sub = (x: number, y: number) => x - y; * var fn = xfunction.curryRight(sub); * fn(2)(3); // sub(3, 2) * // → 1 * * var array = [1]; * var push2 = (x: number, y: number) => array.push(x, y); * var fn = xfunction.curryRight(push2, 2); * fn(2)(3); // push2(3, 2) * array; * // → [1, 3, 2] * ``` */ export declare function curryRight(x: Function, n?: number): Function; /** Invocation control for time/rate-controlled functions. */ export interface InvocationControl { /** Disable invoking of target function. */ clear: () => void; /** Immediately invoke target function. */ flush: () => void; } /** * Generate deferred version of a function, that executes after the current stack has cleared. * @param x a function * @returns (...args) => invocation control * @example * ```javascript * var count = 0; * var fn = xfunction.defer(() => ++count); * fn(); * fn(); * // `count` incremented after 0s * // `count` incremented after 0s * ``` */ export declare function defer(x: Function): Function; /** * Generate delayed version of a function. * @param x a function * @param t delay time (ms) * @returns (...args) => invocation control * @example * ```javascript * var count = 0; * var fn = xfunction.delay(() => ++count, 500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * // `count` incremented after 0.5s * // `count` incremented after 1.5s * * * var count = 0; * var fn = xfunction.delay(() => ++count, 500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * setTimeout(fn, 3000); * // `count` incremented after 0.5s * // `count` incremented after 1.5s * // `count` incremented after 2.5s * // `count` incremented after 3.5s * ``` */ export declare function delay(x: Function, t: number): Function; /** * Generate restricted-use version of a function. * @param x a function * @param start usable from * @param end usable till (excluding) [-1 ⇒ end] * @returns (...args) => x(...args) from [start:end] calls * @example * ```javascript * var sum = 0; * var add = (x: number) => sum += x; * var fn = xfunction.restrict(add, 0, 4); * for (var i=0; i<10; ++i) * fn(i); * sum; // 0 + 1 + 2 + 3 * // → 6 * * * var sum = 0; * var add = (x: number) => sum += x; * var fn = xfunction.restrict(add, 4, 8); * for (var i=0; i<10; ++i) * fn(i); * sum; // 4 + 5 + 6 + 7 * // → 22 * ``` */ export declare function restrict(x: Function, start: number, end?: number): Function; /** * Restrict a function to be used only once. * @param x a function * @returns (...args) => x(...args) from [0:1] calls * @example * ```javascript * var count = 0; * var fn = xfunction.restrictOnce(x => ++count); * for (var i=0; i<10; ++i) * fn(i); * count; * // → 1 * ``` */ export declare function restrictOnce(x: Function): Function; export { restrictOnce as once }; /** * Restrict a function to be used only upto a certain number of calls. * @param x a function * @param n number of calls upto which it is usable * @returns (...args) => x(...args) from [0:n] calls * @example * ```javascript * var count = 0; * var fn = xfunction.restrictBefore(x => ++count, 3); * for (var i=0; i<10; ++i) * fn(i); * count; * // → 3 * ``` */ export declare function restrictBefore(x: Function, n: number): Function; export { restrictBefore as before }; /** * Restrict a function to be used only after a certain number of calls. * @param x a function * @param n number of calls after which it is usable * @returns (...args) => x(...args) from [n:end] calls * @example * ```javascript * var count = 0; * var fn = xfunction.restrictAfter(x => ++count, 3); * for (var i=0; i<10; ++i) * fn(i); * count; * // → 7 * ``` */ export declare function restrictAfter(x: Function, n: number): Function; export { restrictAfter as after }; /** * Generate debounced version of a function. * @param x a function * @param t delay time (ms) * @param T max delay time [-1 ⇒ none] * @returns (...args) => invocation control * @example * ```javascript * var count = 0; * var fn = xfunction.debounce(() => ++count, 1500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * setTimeout(fn, 4000); * setTimeout(fn, 5000); * // `count` incremented after 3.5s * // `count` incremented after 6.5s * * * var count = 0; * var fn = xfunction.debounce(() => ++count, 1500); * setTimeout(fn, 0); * setTimeout(fn, 500); * setTimeout(fn, 1000); * setTimeout(fn, 1500); * setTimeout(fn, 2000); * setTimeout(fn, 4000); * setTimeout(fn, 4500); * setTimeout(fn, 5000); * // `count` incremented after 3.5s * // `count` incremented after 6.5s * * * var count = 0; * var fn = xfunction.debounce(() => ++count, 1500, 3500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * setTimeout(fn, 3000); * setTimeout(fn, 4000); * setTimeout(fn, 6000); * // `count` incremented after 3.5s * // `count` incremented after 5.5s * // `count` incremented after 7.5s * ``` */ export declare function debounce(x: Function, t: number, T?: number): Function; /** * Generate leading-edge debounced version of a function. * @param x a function * @param t delay time (ms) * @param T max delay time [-1 ⇒ none] * @returns (...args) => invocation control * @example * ```javascript * var count = 0; * var fn = xfunction.debounceEarly(() => ++count, 1500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * setTimeout(fn, 4000); * setTimeout(fn, 5000); * // `count` incremented after 0s * // `count` incremented after 4s * * * var count = 0; * var fn = xfunction.debounceEarly(() => ++count, 1500); * setTimeout(fn, 0); * setTimeout(fn, 500); * setTimeout(fn, 1000); * setTimeout(fn, 1500); * setTimeout(fn, 2000); * setTimeout(fn, 4000); * setTimeout(fn, 4500); * setTimeout(fn, 5000); * // `count` incremented after 0s * // `count` incremented after 4s * * * var count = 0; * var fn = xfunction.debounceEarly(() => ++count, 1500, 3500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * setTimeout(fn, 3000); * setTimeout(fn, 4000); * setTimeout(fn, 6000); * // `count` incremented after 0s * // `count` incremented after 4s * // `count` incremented after 6s * ``` */ export declare function debounceEarly(x: Function, t: number, T?: number): Function; /** * Generate throttled version of a function. * @param x a function * @param t wait time (ms) * @returns (...args) => invocation control * @example * ```javascript * var count = 0; * var fn = xfunction.throttle(() => ++count, 2500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * // `count` incremented after 2.5s * * * var count = 0; * var fn = xfunction.throttle(() => ++count, 2500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * setTimeout(fn, 3000); * setTimeout(fn, 4000); * // `count` incremented after 2.5s * // `count` incremented after 5.5s * ``` */ export declare function throttle(x: Function, t: number): Function; /** * Generate leading-edge throttled version of a function. * @param x a function * @param t wait time (ms) * @returns (...args) => invocation control * @example * ```javascript * var count = 0; * var fn = xfunction.throttleEarly(() => ++count, 2500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * // `count` incremented after 0s * * * var count = 0; * var fn = xfunction.throttleEarly(() => ++count, 2500); * setTimeout(fn, 0); * setTimeout(fn, 1000); * setTimeout(fn, 2000); * setTimeout(fn, 3000); * setTimeout(fn, 4000); * // `count` incremented after 0s * // `count` incremented after 3s * ``` */ export declare function throttleEarly(x: Function, t: number): Function;