UNPKG

@7urtle/lambda

Version:

Functional programming library in JavaScript.

231 lines (220 loc) 5.54 kB
import { isArray, isEqual, isString, isObject, isFunction, isNull, isUndefined } from "./conditional.js"; import {keysOf, join} from "./list.js"; import {map} from "./core.js"; import {nary} from "./arity.js"; /** * typeOf outputs a type of its input. * * @HindleyMilner typeOf :: a -> string * * @pure * @param {*} a * @return {string} * * @example * import {typeOf} from '@7urtle/lambda'; * * typeOf('7turtle'); // => 'string' */ export const typeOf = a => typeof a; /** * lengthOf outputs the length of an input. * * @HindleyMilner lengthOf :: (string|array) -> number * * @pure * @param {string|array} a * @return {number} * * @example * import {lengthOf} from '@7urtle/lambda'; * * lengthOf('7turtle'); // => 7 * lengthOf([1,2,3]); // => 3 * lengthOf({}); // => undefined */ export const lengthOf = a => a.length; /** * passThrough output is the same as input a. passThrough executes function passed as first argument. * * passThrough can be called both as a curried unary function or as a standard binary function. * * @HindleyMilner passThrough :: function -> a -> a * * @pure * @param {function} fn * @param {*} anything * @return {boolean} * * @example * import {passThrough} from '@7urtle/lambda'; * * passThrough(() => 'b')('a'); // => 'a' * * // isTypeOf can be called both as a curried unary function or as a standard binary function * passThrough(() => 'b')('a') === passThrough(() => 'b', 'a'); */ export const passThrough = nary(fn => anything => { fn(anything); return anything; }); /** * log output is the same as input and it logs the input value. log causes side effect of console.log. * * @HindleyMilner log :: a -> a * * @param {*} anything * @return {*} * * @example * import {log} from '@7urtle/lambda'; * * log('anything'); // => 'anything' */ export const log = passThrough(console.log); /** * spy output is the same as input and it logs the deepInspect of the input. spy causes side effect of console.log. * * @HindleyMilner spy :: a -> a * * @param {*} anything * @return {*} * * @example * import {spy} from '@7urtle/lambda'; * * spy([1, 'a']); // => "[1, 'a']" */ export const spy = passThrough(a => console.log(deepInspect(a))); /** * minusOneToUndefined output is the same as input or undefined if input is -1. * * Because some functions return -1 as error state, this function is created to change it into a more consistent * undefined output. * * @HindleyMilner minusOneToUndefined :: a -> a|boolean * * @pure * @param {*} anything * @return {*|boolean} * * @example * import {log} from '@7urtle/lambda'; * * minusOneToUndefined(-1); // => undefined * minusOneToUndefined(0); // => 0 * minusOneToUndefined('7urtle'); // => '7urtle' */ export const minusOneToUndefined = anything => isEqual(-1)(anything) ? undefined: anything; /** * inspectFunction outputs name of named function or its conversion to string. * * @HindleyMilner inspectFunction :: (a -> b) -> string * * @pure * @param {function} fn * @return {string} * * @example * import {inspectFunction} from '@7urtle/lambda'; * * function namedFunction() { * return null; * } * * inspectFunction(namedFunction); // => 'namedFunction' * inspectFunction(() => 'b'); * // => `function () { * // => return 'b'; * // => }` */ export const inspectFunction = fn => fn.name ? fn.name : String(fn); /** * inspectArray maps over input array [a] and outputs string representing it. * * @HindleyMilner inspectArray :: [a] -> string * * @pure * @param {array} a * @return {string} * * @example * import {inspectArray} from '@7urtle/lambda'; * * function namedFunction() { * return null; * } * * inspectArray([1, 'a']); // => "[1, 'a']" * inspectArray([namedFunction, 'a']); // => "[namedFunction, 'a']" */ export const inspectArray = a => `[${join(', ')(map(deepInspect)(a))}]`; /** * inspectString outputs string representing input. * * @HindleyMilner inspectString :: a -> string * * @pure * @param {*} a * @return {string} * * @example * import {inspectString} from '@7urtle/lambda'; * * inspectString('my string'); // => "'my string'" */ export const inspectString = a => `'${a}'`; /** * inspectObject outputs string representing input. * * @HindleyMilner inspectObject :: a -> string * * @pure * @param {object} a * @return {string} * * @example * import {inspectObject} from '@7urtle/lambda'; * * inspectObject({a: 'b'}); // => "{a: 'b'}" */ export const inspectObject = a => isFunction(a.inspect) ? a.inspect() : `{${join(', ')(map(join(': '))(map(k => [k, deepInspect(a[k])])(keysOf(a))))}}` /** * deepInspect runs recursively over input and outputs string representing the input. * * @HindleyMilner deepInspect :: a -> string * * @pure * @param {*} a * @return {string} * * @example * import {deepInspect} from '@7urtle/lambda'; * * function namedFunction() { * return null; * } * * deepInspect({a: 'b'}); // => "{a: 'b'}" * deepInspect(namedFunction); // => 'namedFunction' * deepInspect([1, 'a']); // => "[1, 'a']" * deepInspect('my string'); // => "'my string'" * deepInspect(undefined); // => 'undefined' */ export const deepInspect = a => isUndefined(a) ? 'undefined' : isNull(a) ? 'null' : isFunction(a) ? inspectFunction(a) : isArray(a) ? inspectArray(a) : isObject(a) ? inspectObject(a) : isString(a) ? inspectString(a) : String(a);