UNPKG

@hgargg-0710/one

Version:

A tiny npm library purposed for providing beautiful solutions to frequent miniature (one-line/one-expression) tasks for various JS datatypes.

122 lines (121 loc) 4.43 kB
import { last, lastOut, substitute } from "../array/array.js"; import { not, T } from "../boolean/boolean.js"; import { max } from "../number/number.js"; import { isUndefined } from "../type/type.js"; /** * Provided with a list of functions, lazily executes them in sequence * and returns the first truthy result. * If all results are falsy - returns the last one */ export const or = (...fs) => (...x) => fs.reduce((prev, curr) => (prev ? prev : curr(...x)), false); /** * Provided with a list of functions, lazily executes them in sequence * and returns the first falsy result. * If all results are truthy - returns the last one */ export const and = (...fs) => (...x) => fs.reduce((prev, curr) => (prev ? curr(...x) : prev), true); /** * Returns the function composition of the `fs` functions. */ export const trivialCompose = (...fs) => (...x) => lastOut(fs).reduceRight((last, curr) => curr(last), (last(fs) || id)(...x)); /** * Returns the array, containing the values of `f(j * i)` for `0 <= i <= floor(n / j)` */ export const iterations = (f, n, j = 1) => Array.from({ length: Math.floor(n / j) + +(j > 1) }, (_x, i) => f(j * i)); /** * Creates a new array `X` = [init], * that is then filled with `n` iterations of `f(last(X), i, X)`, * and returned */ export const sequence = (f, n) => (init) => { const seqres = [init]; for (let i = 0; i < n; ++i) seqres.push(f(last(seqres), i, seqres)); return seqres; }; /** * Makes the calls `f(0), f(1), ..., f(n)` */ export const repeat = (f, n) => { for (let i = 0; i < n; ++i) f(i); }; /** * Returns a composition, such that expected output of the given functions are arrays * intended to be spread out as inputs for the next function. */ export const arrayCompose = (...fs) => (...x) => fs.reduceRight((last, curr) => curr(...last), x); /** * Creates and returns a `Map`, filled with key-value pairs of `[x, f(x)]` with `x` being in `keys` */ export const cache = (f, keys) => new Map(keys.map((x) => [x, f(x)])); /** * Breaks the given inputs' array `x` into (possibly intersecting) segments using `x.slice(inds[i])`, * then - calls the respective function with each segment, and returns all of the calls' * return values in an array. * * A missing `x.slice`-interval defaults to `[]` (whole signature copying) */ export const tupleSlice = (...fs) => (...inds) => (...x) => fs.map((f, i) => f(...x.slice(...(inds[i] || [])))); /** * Similar to `tupleSlice`, only difference being that `inds` are now predicates, * using which the signatures for each particular function are `x.filter(inds[i])`-ed * * Like with `tupleSlice`, the default is copying of the entire signature `.filter(T)` */ export const tuplePick = (...fs) => (...inds) => (...x) => fs.map((f, i) => f(...x.filter(inds[i] || T))); /** * Returns a function, the inputs of which are cached on each call. */ export const cached = (base) => { const cachef = function (x) { const cacheval = cachef.cache.get(x); if (!isUndefined(cacheval)) return cacheval; const retres = base(x); cachef.cache.set(x, retres); return retres; }; cachef.cache = new Map(); return cachef; }; /** * Identity function */ export const id = (x) => x; /** * No-op function */ export const nil = () => { }; /** * Creates a new function calling `f`, with arguments at positions defined by `indexes` Set * filled with values from `values`, and the remaining arguments filled with values from 'x'. */ export const argFiller = (f) => { return (...indexes) => { const substitutionForm = substitute(f.length, indexes); return (...values) => { const substituter = substitutionForm(values); return (...x) => f(...substituter(x)); }; }; }; /** * Returns `f.bind(bound)`. `bound` defaults to `null` */ export const copy = (f, bound = null) => f.bind(bound); /** * Returns a function returning `set.has(x)` */ export const has = (set) => (x) => set.has(x); /** * Returns a function that removes last `n` arguments * (or, all of them, if it is greater than `args.length`) from `args`, * and calls `f` on the result */ export const argWaster = (f) => (n = Infinity) => (...args) => f(...args.slice(0, max(0, args.length - n))); /** * Returns `(...x) => !f(...x)` */ export const negate = (f) => trivialCompose(not, f); export * from "./constant.js";