UNPKG

@beenotung/tslib

Version:
295 lines 9.1 kB
"use strict"; /** * Created by beenotung on 12/26/16. * the curried functions are deprecated due to type system limit */ Object.defineProperty(exports, "__esModule", { value: true }); exports.map2 = exports.update = exports.groupByAll = exports.mergeObjs = exports.pushAll = exports.concatAll = exports.concat = exports.foldl1 = exports.foldl = exports.groupBy = exports.getOrSetDefault = exports.map = exports.fmap = exports.concatWithoutDup = exports.iteratorsToArray = exports.doAll = exports.chainFs = exports.composeFs = exports.symbolF = exports.notnot = exports.not = exports.or = exports.and = exports.divMod = exports.quotMod = exports.quot = exports.div = exports.rem = exports.mult = exports.minus = exports.add = exports.defineSymbolF = exports.any = exports.first = exports.lt = exports.gt = exports.neq = exports.eq = exports.none = exports.just = exports.forEach = exports.isStringType = exports.isNumberType = exports.isFunctionType = exports.symbolFs = exports.echoF = exports.apply2 = exports.countWhere = exports.even = exports.odd = exports.compose2 = exports.liftError_noarg = exports.liftError = exports.lift_noarg = exports.lift = exports.flip = exports.compose = exports.filter = exports.length = exports.setProp = exports.deepProp = exports.prop = exports.apply = void 0; const curry_1 = require("./curry"); const map_1 = require("./map"); /** take all args (ignore arity) * apply :: (..args->a) -> ...args -> a * */ exports.apply = curry_1.curry((f) => function () { return curry_1.id(f.apply(null, arguments)); }); exports.prop = curry_1.curry((name, o) => o[name]); /** cannot represent recursive type, o must eventually contains type A */ exports.deepProp = curry_1.curry((name, o) => { if (o[name] !== void 0) { return o[name]; } else { return name.split('.').reduce((acc, c) => acc[c], o); } }); /** * @remark side effect * @return original object * * setProp :: a -> k -> {k:a} -> {k:a} * */ exports.setProp = curry_1.curry((a, k, o) => { o[k] = a; return o; }); exports.length = curry_1.curry((x) => x.length); exports.filter = curry_1.curry((f, xs) => xs.filter(f)); exports.compose = curry_1.curry((f, g, a) => f(g(a))); /** * flip :: (a->b) -> (b->a) * */ exports.flip = curry_1.curry((f) => (b) => (a) => f(a, b)); /** * lift :: a -> b -> a * */ exports.lift = curry_1.curry((a, b) => a); exports.lift_noarg = curry_1.curry((a) => () => a); exports.liftError = curry_1.curry((e, b) => { throw e; }); exports.liftError_noarg = curry_1.curry((e) => () => { throw e; }); exports.compose2 = exports.compose(exports.compose, exports.compose); exports.odd = curry_1.curry((x) => x % 2 === 1); exports.even = curry_1.curry((x) => x % 2 === 0); exports.countWhere = curry_1.curry(exports.compose2(exports.length, exports.filter)); /** * @remark side effect * apply2 :: (a->*) -> (a->b) -> a -> b * */ exports.apply2 = curry_1.curry((f, g, x) => { f(x); return g(x); }); /** * echoF :: (a->*) -> a -> a * @example echoF (console.log) (1) ~> console.log(1) +> return 1 * */ exports.echoF = exports.flip(exports.apply2)(curry_1.id); exports.symbolFs = new Map(); exports.isFunctionType = (x) => typeof x === 'function'; exports.isNumberType = (x) => typeof x === 'number'; exports.isStringType = (x) => typeof x === 'string'; /** * @remark side effect * * forEach :: (a->*) -> [a] -> * * */ exports.forEach = curry_1.curry((f, xs) => { /* xs is ArrayLike, might not has forEach */ const n = xs.length; for (let i = 0; i < n; i++) { f(xs[i]); } }); /** * just :: a -> [a] * */ exports.just = curry_1.curry((x) => [x]); /** * none :: * -> [] * */ exports.none = curry_1.curry((x) => []); exports.eq = curry_1.curry((a, b) => b === a); exports.neq = curry_1.curry((a, b) => b !== a); exports.gt = curry_1.curry((a, b) => b > a); exports.lt = curry_1.curry((a, b) => b < a); /** * first :: (a->Bool) -> [a] -> MaybeSingleton a * */ exports.first = curry_1.curry((f, xs) => { for (const x of xs) { if (f(x)) { return exports.just(x); } } return exports.none(); }); /** * any :: (a->Bool) -> [a] -> Bool * */ exports.any = curry_1.curry((f, xs) => { for (const x of xs) { if (f(x)) { return true; } } return false; }); /** * @remark side effect * define infix operator (binary function) * */ exports.defineSymbolF = curry_1.curry((name, f) => { exports.symbolFs.set(name, f); return f; }); /* number | string atomically for a and b */ exports.add = exports.defineSymbolF('+', (a, b) => b + a); /* number | string atomically for a and b */ exports.minus = exports.defineSymbolF('-', (a, b) => b - a); exports.mult = exports.defineSymbolF('*', (a, b) => b * a); exports.defineSymbolF('/', (a, b) => b / a); exports.rem = exports.defineSymbolF('%', (a, b) => b % a); exports.div = curry_1.curry((a, b) => Math.floor(b / a)); /* tslint:disable no-bitwise */ exports.quot = curry_1.curry((a, b) => (b / a) | 0); /** faster */ exports.quotMod = curry_1.curry((a, b) => [ (b / a) | 0, b % a, ]); /* tslint:enable no-bitwise */ /* slower */ exports.divMod = curry_1.curry((a, b) => { const d = Math.floor(b / a); return [d, b - d * a]; }); exports.and = exports.defineSymbolF('&&', (a, b) => b && a); exports.or = exports.defineSymbolF('||', (a, b) => b || a); exports.not = exports.defineSymbolF('!', (a) => !a); exports.notnot = exports.defineSymbolF('!!', (a) => !!a); exports.symbolF = curry_1.curry((name) => exports.symbolFs.get(name) || (() => { throw new Error('symbol ' + name + ' is not defined'); })()); exports.composeFs = curry_1.curry((fs, acc) => { for (let i = fs.length - 1; i >= 0; i--) { acc = fs[i](acc); } return acc; }); exports.chainFs = curry_1.curry((fs, acc) => { for (const f of fs) { acc = f(acc); } return acc; }); /** * @remark side effect * f :: unary function <A,B> * args :: ArrayLike<A> * */ exports.doAll = curry_1.curry((f, args) => { for (const arg of args) { f(arg); } }); /** * flatten the iterators as a single array * */ function iteratorsToArray(itrs) { const xs = []; for (const itr of itrs) { xs.push(...Array.from(itr)); } return xs; } exports.iteratorsToArray = iteratorsToArray; exports.concatWithoutDup = curry_1.curry((as, bs) => { const acc = new Set(); exports.doAll((as) => exports.doAll((a) => acc.add(a), as), [as, bs]); return iteratorsToArray([acc.values()]); }); exports.fmap = curry_1.curry((f, as) => as.map(f)); /**@deprecated*/ exports.map = exports.fmap; /**@deprecated use mapGetOrSetDefault in map.ts */ exports.getOrSetDefault = curry_1.curry((v, k, m) => { if (m.has(k)) { return m.get(k); } m.set(k, v); return v; }); /** * groupBy :: (a->k) , [a] -> Map k [a] * */ function groupBy(f, xs) { const res = new Map(); for (const x of xs) { map_1.mapGetOrSetDefault(res, f(x), () => []).push(x); } return res; } exports.groupBy = groupBy; /** * foldl :: (b->a->b) -> b -> [a] -> b * */ exports.foldl = curry_1.curry((f, acc, xs) => { for (let i = 0, n = xs.length; i < n; i++) { acc = f(acc, xs[i]); } return acc; }); exports.foldl1 = curry_1.curry((f, xs) => { const n = xs.length; if (n === 0) { throw new TypeError('xs should be non-empty ArrayLike<*>'); } let acc = xs[0]; for (let i = 1; i < n; i++) { acc = f(acc, xs[i]); } return acc; }); /** * concat :: [a] -> [a] -> [a] * */ exports.concat = curry_1.curry((as, bs) => as.concat(bs)); /** * concatAll :: [[a]] -> [a] * */ exports.concatAll = exports.foldl(exports.concat, []); /** * @remark side effect to as * as -> bs -> __update as__ * */ exports.pushAll = curry_1.curry((as, bs) => as.push(...bs)); /** * merge array of plain objects * do not support merging functions * do not support instant object (e.g. Map instance) * merge :: [a|b] -> a & b * */ exports.mergeObjs = curry_1.curry((xs) => Object.assign({}, ...xs)); // /** // * mergeAll :: (a=>) -> [a] -> [a] -> [a] // * */ // export const mergeAll = curry((f, as, bs) => { // as = groupBy(f, as); // bs = groupBy(f, bs); // const res = []; // forEach(xs => pushAll(res), as); // forEach(xs => pushAll(res), bs); // return res; // }); /** * groupByAll :: (a->k) -> [[a]] -> Map k [a] * */ exports.groupByAll = curry_1.curry((f, xss) => { const res = new Map(); for (const xs of xss) { for (const x of xs) { exports.getOrSetDefault([], f(x), res).push(x); } } return res; }); /** * @remark side effect * update :: (a->__update a__) -> [a] -> [a] * @return original array * * more effective then using map if the original array is going to be discarded anyway * */ exports.update = curry_1.curry((f, as) => { as.forEach(f); return as; }); exports.map2 = curry_1.curry((f, xss) => { return xss.map(xs => xs.map(f)); }); //# sourceMappingURL=functional.js.map