fpo
Version:
FP library for JavaScript. Supports named-argument style methods.
907 lines (742 loc) • 24.1 kB
JavaScript
(function UMD(name,context,definition){
/* istanbul ignore next */if (typeof define === "function" && define.amd) { define(definition); }
/* istanbul ignore next */else if (typeof module !== "undefined" && module.exports) { module.exports = definition(); }
/* istanbul ignore next */else { context[name] = definition(name,context); }
})("FPO",this,function DEF(name,context){
"use strict";
var publicAPI = {
identity: curryMultiple( {fn: identity, n: 1} ),
constant: curryMultiple( {fn: constant, n: 1} ),
pick: curryMultiple( {fn: pick, n: 2} ),
pickAll: curryMultiple( {fn: pickAll, n: 2} ),
nAry: curryMultiple( {fn: nAry, n: 2} ),
unary: curryMultiple( {fn: unary, n: 2} ),
binary: curryMultiple( {fn: binary, n: 2} ),
curry: curryMultiple( {fn: curry, n: 1} ),
curryMultiple: curryMultiple( {fn: curryMultiple, n: 1} ),
uncurry: curryMultiple( {fn: uncurry, n: 1} ),
partial: curryMultiple( {fn: partial, n: 2 } ),
complement: curryMultiple( {fn: complement, n: 1} ),
apply: curryMultiple( {fn: apply, n: 1} ),
unapply: curryMultiple( {fn: unapply, n: 2} ),
compose: curryMultiple( {fn: compose, n: 1} ),
pipe: curryMultiple( {fn: pipe, n: 1} ),
prop: curryMultiple( {fn: prop, n: 2} ),
setProp: curryMultiple( {fn: setProp, n: 3} ),
reassoc: curryMultiple( {fn: reassoc, n: 2} ),
filterIn: curryMultiple( {fn: filterIn, n: 2} ),
filterInObj: curryMultiple( {fn: filterInObj, n: 2} ),
filterOut: curryMultiple( {fn: filterOut, n: 2} ),
filterOutObj: curryMultiple( {fn: filterOutObj, n: 2} ),
map: curryMultiple( {fn: map, n: 2} ),
mapObj: curryMultiple( {fn: mapObj, n: 2} ),
flatMap: curryMultiple( {fn: flatMap, n: 2} ),
flatMapObj: curryMultiple( {fn: flatMapObj, n: 2} ),
ap: curryMultiple( {fn: ap, n: 2} ),
reduce: curryMultiple( {fn: reduce, n: 2} ),
reduceObj: curryMultiple( {fn: reduceObj, n: 2} ),
reduceRight: curryMultiple( {fn: reduceRight, n: 2} ),
flatten: curryMultiple( {fn: flatten, n:1} ),
zip: curryMultiple( {fn: zip, n: 2} ),
trampoline: curryMultiple( {fn: trampoline, n: 1} ),
transducers: {
transduce: curryMultiple( {fn: transduce, n: 4} ),
into: curryMultiple( {fn: into, n: 3} ),
map: curryMultiple( {fn: transducerMap, n: 1} ),
filter: curryMultiple( {fn: transducerFilter, n: 1} ),
string: curryMultiple( {fn: strConcat, n: 2} ),
array: curryMultiple( {fn: arrayPush, n: 2} ),
number: curryMultiple( {fn: numericAdd, n: 2} ),
booleanAnd: curryMultiple( {fn: booleanAnd, n: 2} ),
booleanOr: curryMultiple( {fn: booleanOr, n: 2} ),
default: curryMultiple( {fn: ({ acc }) => acc, n: 1} ),
},
head: curryMultiple( {fn: head, n: 1} ),
tail: curryMultiple( {fn: tail, n: 1} ),
take: curryMultiple( {fn: take, n: 1} ),
memoize: curryMultiple( {fn: memoize, n: 1} ),
remap: curryMultiple( {fn: remap, n: 2} ),
};
publicAPI.std = {
identity: stdCurryMultiple( unapply( {fn: identity, props: ["v"]} ), /*arity=*/1 ),
constant: stdCurryMultiple( unapply( {fn: constant, props: ["v"]} ), /*arity=*/1 ),
pick: stdCurryMultiple( unapply( {fn: pick, props: ["props","v"]} ), /*arity=*/2 ),
pickAll: stdCurryMultiple( unapply( {fn: pickAll, props: ["props","v"]} ), /*arity=*/2 ),
nAry: stdCurryMultiple( stdNAry, /*arity=*/2 ),
unary: stdCurryMultiple( stdUnary, /*arity=*/1 ),
binary: stdCurryMultiple( stdBinary, /*arity=*/1 ),
curry: stdCurryMultiple( stdCurry, /*arity=*/1 ),
curryMultiple: stdCurryMultiple( stdCurryMultiple, /*arity=*/1 ),
uncurry: stdCurryMultiple( stdUncurry, /*arity=*/1 ),
partial: stdCurryMultiple( stdPartial, /*arity=*/2 ),
partialRight: stdCurryMultiple( stdPartialRight, /*arity=*/2 ),
complement: stdCurryMultiple( unapply( {fn: complement, props: ["fn"]} ), /*arity=*/1 ),
apply: stdCurryMultiple( stdApply, /*arity=*/1 ),
unapply: stdCurryMultiple( stdUnapply, /*arity=*/1 ),
compose: stdCurryMultiple( stdCompose, /*arity=*/1 ),
pipe: stdCurryMultiple( stdPipe, /*arity=*/1 ),
prop: stdCurryMultiple( unapply( {fn: prop, props: ["prop","v"]} ), /*arity=*/2 ),
setProp: stdCurryMultiple( unapply( {fn: setProp, props: ["prop","o","v"]} ), /*arity=*/3 ),
reassoc: stdCurryMultiple( unapply( {fn: reassoc, props: ["props","v"]} ), /*arity=*/2 ),
filterIn: stdCurryMultiple( unapply( {fn: _applyFnProp( filterIn, ["v","i","arr"] ), props: ["fn","arr"]} ), /*arity=*/2 ),
filterInObj: stdCurryMultiple( unapply( {fn: _applyFnProp( filterInObj, ["v","i","o"] ), props: ["fn","o"]} ), /*arity=*/2 ),
filterOut: stdCurryMultiple( unapply( {fn: _applyFnProp( filterOut, ["v","i","arr"] ), props: ["fn","arr"]} ), /*arity=*/2 ),
filterOutObj: stdCurryMultiple( unapply( {fn: _applyFnProp( filterOutObj, ["v","i","o"] ), props: ["fn","o"]} ), /*arity=*/2 ),
map: stdCurryMultiple( unapply( {fn: _applyFnProp( map, ["v","i","arr"] ), props: ["fn","arr"]} ), /*arity=*/2 ),
mapObj: stdCurryMultiple( unapply( {fn: _applyFnProp( mapObj, ["v","i","o"] ), props: ["fn","o"]} ), /*arity=*/2 ),
flatMap: stdCurryMultiple( unapply( {fn: _applyFnProp( flatMap, ["v","i","arr"] ), props: ["fn","arr"]}), /*arity=*/2 ),
flatMapObj: stdCurryMultiple( unapply( {fn: _applyFnProp( flatMapObj, ["v","i","o"] ), props: ["fn","o"]}), /*arity=*/2 ),
ap: stdCurryMultiple( stdAp, /*arity=*/2 ),
reduce: stdCurryMultiple( unapply( {fn: _applyFnProp( reduce, ["acc","v","i","arr"] ), props: ["fn","v","arr"]} ), /*arity=*/3 ),
reduceObj: stdCurryMultiple( unapply( {fn: _applyFnProp( reduceObj, ["acc","v","i","o"] ), props: ["fn","v","o"]} ), /*arity=*/3 ),
reduceRight: stdCurryMultiple( unapply( {fn: _applyFnProp( reduceRight, ["acc","v","i","arr"] ), props: ["fn","v","arr"]} ), /*arity=*/3 ),
flatten: stdCurryMultiple( unapply( {fn: flatten, props: ["v","n"]} ), /*arity=*/1 ),
zip: stdCurryMultiple( unapply( {fn: zip, props: ["arr1","arr2"]} ), /*arity=*/2 ),
trampoline: stdCurryMultiple( unapply( {fn: trampoline, props: ["fn"]} ), /*arity=*/1 ),
transducers: {
transduce: stdCurryMultiple( stdTransduce, /*arity=*/4 ),
into: stdCurryMultiple( stdInto, /*arity=*/3 ),
map: stdCurryMultiple( stdTransducerMap, /*arity=*/2 ),
filter: stdCurryMultiple( stdTransducerFilter, /*arity=*/2 ),
string: stdCurryMultiple( stdStrConcat, /*arity=*/2 ),
array: stdCurryMultiple( stdArrayPush, /*arity=*/2 ),
number: stdCurryMultiple( stdNumericAdd, /*arity=*/2 ),
booleanAnd: stdCurryMultiple( stdBooleanAnd, /*arity=*/2 ),
booleanOr: stdCurryMultiple( stdBooleanOr, /*arity=*/2 ),
default: stdCurryMultiple( acc => acc, /*arity=*/1 ),
},
flip: stdCurryMultiple( stdFlip, /*arity=*/1 ),
reverseArgs: stdCurryMultiple( stdReverseArgs, /*arity=*/1 ),
head: stdCurryMultiple( unapply( {fn: head, props: ["v"]} ), /*arity=*/1 ),
tail: stdCurryMultiple( unapply( {fn: tail, props: ["v"]} ), /*arity=*/1 ),
take: stdCurryMultiple( unapply( {fn: take, props: ["v","n"]} ), /*arity=*/1 ),
memoize: stdCurryMultiple( unapply( {fn: memoize, props: ["fn","n"]} ), /*arity=*/1 ),
remap: stdCurryMultiple( unapply( {fn: remap, props: ["fn","args"]} ), /*arity=*/2 ),
};
// method convenience aliases
_setMethodAlias("constant","always");
_setMethodAlias("pipe","flow");
_setMethodAlias("pipe","sequence");
_setMethodAlias("compose","flowRight");
_setMethodAlias("apply","spread");
_setMethodAlias("unapply","gather");
_setMethodAlias("setProp","assoc");
_setMethodAlias("filterIn","filter");
_setMethodAlias("filterIn","keep");
_setMethodAlias("filterInObj","filterObj");
_setMethodAlias("filterInObj","keepObj");
_setMethodAlias("filterOut","reject");
_setMethodAlias("filterOutObj","rejectObj");
_setMethodAlias("flatMap","chain");
_setMethodAlias("flatMapObj","chainObj");
_setMethodAlias("reduce","fold");
_setMethodAlias("reduceObj","foldObj");
_setMethodAlias("reduce","foldL");
_setMethodAlias("reduceRight","foldR");
publicAPI.partialRight = publicAPI.partial;
publicAPI.transducers.boolean = publicAPI.transducers.booleanAnd;
publicAPI.std.transducers.boolean = publicAPI.std.transducers.booleanAnd;
return publicAPI;
// ***************************************
function identity({ v }) {
return v;
}
function constant({ v }) {
return function value(){
return v;
};
}
function pick({ v: obj, props = [] }) {
var newObj = {};
for (let prop of props) {
if (_hasProp( obj, prop )) {
newObj[prop] = obj[prop];
}
}
return newObj;
}
function pickAll({ v: obj, props = [] }) {
var newObj = {};
for (let prop of props) {
newObj[prop] = obj[prop];
}
return newObj;
}
function nAry({ fn, props = [] }) {
return function limited(argsObj = {}){
return fn( pick( {v: argsObj, props} ) );
};
}
function stdNAry(fn,n = 0) {
n = Number( n );
return function nary(...args){
return fn( ...args.slice( 0, Math.max( 0, n ) ) );
};
}
function unary({ fn, prop: propName1 = "" }) {
return nAry( {fn, props: [propName1]} );
}
function stdUnary(fn) {
return stdNAry( fn, 1 );
}
function binary({ fn, props: [ propName1 = "", propName2 = "" ] = [] }) {
return nAry( {fn, props: [propName1,propName2]} );
}
function stdBinary(fn) {
return stdNAry( fn, 2 );
}
function curry({ fn, n: arity = 1 }) {
arity = Number( arity );
return (function nextCurried(prevArgsObj){
return function curried(nextArgsObj = {}){
var keys = Object.keys( nextArgsObj );
var allArgsObj = (keys.length > 0) ?
Object.assign( {}, prevArgsObj, {[keys[0]]: nextArgsObj[keys[0]]} ) :
prevArgsObj;
if (Object.keys( allArgsObj ).length >= arity) {
return fn( allArgsObj );
}
else {
return nextCurried( allArgsObj );
}
};
})( {} );
}
function stdCurry(fn,arity = Math.max( 1, fn.length)) {
arity = Number( arity );
return (function nextCurried(prevArgs){
return function curried(...nextArgs){
var allArgs = (nextArgs.length > 0) ?
prevArgs.concat( [nextArgs[0]] ) :
prevArgs;
if (allArgs.length >= arity) {
return fn( ...allArgs );
}
else {
return nextCurried( allArgs );
}
};
})( [] );
}
function curryMultiple({ fn, n: arity = 1 }) {
arity = Number( arity );
return (function nextCurried(prevArgsObj){
return function curried(nextArgsObj = {}){
var allArgsObj = (Object.keys( nextArgsObj ).length > 0) ?
Object.assign( {}, prevArgsObj, nextArgsObj ) :
prevArgsObj;
if (Object.keys( allArgsObj ).length >= arity) {
return fn( allArgsObj );
}
else {
return nextCurried( allArgsObj );
}
};
})( {} );
}
function stdCurryMultiple(fn,arity = Math.max( 1, fn.length)) {
arity = Number( arity );
return (function nextCurried(prevArgs){
return function curried(...nextArgs){
var allArgs = (nextArgs.length > 0) ?
prevArgs.concat( nextArgs ) :
prevArgs;
if (allArgs.length >= arity) {
return fn( ...allArgs );
}
else {
return nextCurried( allArgs );
}
};
})( [] );
}
function uncurry({ fn }) {
return function uncurried(argsObj = {}){
var ret = fn;
for (let prop of Object.keys( argsObj )) {
// assume `fn` is strictly curried (needs props one at a time),
// instead of loose/multiple currying
ret = ret( {[prop]: argsObj[prop]} );
}
return ret;
};
}
function stdUncurry(fn) {
return function uncurried(...args){
var ret = fn;
for (let v of args) {
// assume `fn` is strictly curried (needs one arg at a time),
// instead of loose/multiple currying
ret = ret( v );
}
return ret;
};
}
function partial({ fn, args: partialArgsObj = {} }) {
return function partiallyApplied(restArgsObj = {}){
return fn( Object.assign( {}, partialArgsObj, restArgsObj ) );
};
}
function stdPartial(fn,partialArgs = []) {
return function partiallyApplied(...restArgs){
return fn( ...partialArgs, ...restArgs );
};
}
function stdPartialRight(fn,partialArgs = []) {
return function partiallyApplied(...restArgs){
return fn( ...restArgs, ...partialArgs );
};
}
function complement({ fn: predicateFn }) {
return function complemented(...args){
return !predicateFn( ...args );
};
}
function apply({
fn,
props: propNamesInOrder = fn.toString()
.replace( /^(?:(?:function.*\(([^]*?)\))|(?:([^\(\)]+?)\s*=>)|(?:\(([^]*?)\)\s*=>))[^]+$/, "$1$2$3" )
.split( /\s*,\s*/ )
.map( v => v.replace( /[=\s].*$/, "" ) )
}) {
return function appliedFn(argsObj) {
return fn( ...propNamesInOrder.map( function getPropVal(k) { return argsObj[k]; } ) );
};
}
function stdApply(fn) {
return function appliedFn(argsArr) {
return fn( ...argsArr );
};
}
function unapply({ fn, props: propNamesInOrder = [] }) {
return function unappliedFn(...args) {
var argsObj = {};
var i1 = 0;
var i2 = 0;
while (i1 < propNamesInOrder.length && i2 < args.length) {
argsObj[propNamesInOrder[i1++]] = args[i2++];
}
return fn( argsObj );
};
}
function stdUnapply(fn) {
return function unappliedFn(...argsArr) {
return fn( argsArr );
};
}
function compose({ fns = [] }) {
return function composed( {v: result} ){
for (let i = fns.length - 1; i >= 0; i--) {
result = fns[i]( {v: result} );
}
return result;
};
}
function stdCompose(fns = []) {
return function composed(result){
for (let i = fns.length - 1; i >= 0; i--) {
result = fns[i]( result );
}
return result;
};
}
function pipe({ fns = [] }) {
return function piped( {v: result} ){
for (let fn of fns) {
result = fn( {v: result} );
}
return result;
};
}
function stdPipe(fns = []) {
return function piped(result){
for (let fn of fns) {
result = fn( result );
}
return result;
};
}
function prop({ prop = "", v: obj = {} }) {
return obj[prop];
}
function setProp({ prop = "", o: obj = {}, v }) {
obj = Object.assign( {}, obj );
obj[prop] = v;
return obj;
}
function reassoc({ props = {}, v }) {
var obj = {};
var sourceProps = Object.keys( props );
// first, remap specified properties
for (let sourceProp of sourceProps) {
if (sourceProp in v) {
obj[props[sourceProp]] = v[sourceProp];
}
}
// then, copy (only) other properties
for (let prop of Object.keys( v )) {
if (!~sourceProps.indexOf( prop )) {
obj[prop] = v[prop];
}
}
return obj;
}
function filterIn({ fn: predicateFn, arr = [] }) {
var newArr = [];
for (let [i,v] of arr.entries()) {
if (predicateFn( {v, i, arr} )) {
newArr[newArr.length] = v;
}
}
return newArr;
}
function filterInObj({ fn: predicateFn, o = {} }) {
var newObj = {};
for (let i of Object.keys( o )) {
if (predicateFn( {v: o[i], i, o} )) {
newObj[i] = o[i];
}
}
return newObj;
}
function filterOut({ fn: predicateFn, arr = [] }) {
return filterIn( {fn: complement( {fn: predicateFn} ), arr} );
}
function filterOutObj({ fn: predicateFn, o = {} }) {
return filterInObj( {fn: complement( {fn: predicateFn} ), o} );
}
function map({ fn: mapperFn, arr = [] }) {
var newArr = [];
for (let [i,v] of arr.entries()) {
newArr[i] = mapperFn( {v, i, arr} );
}
return newArr;
}
function mapObj({ fn: mapperFn, o = {} }) {
var newObj = {};
for (let i of Object.keys( o )) {
newObj[i] = mapperFn( {v: o[i], i, o} );
}
return newObj;
}
function flatMap({ fn: mapperFn, arr = [] }) {
var newArr = [];
for (let [i,v] of arr.entries()) {
newArr = newArr.concat( mapperFn( {v, i, arr} ) );
}
return newArr;
}
function flatMapObj({ fn: mapperFn, o = {} }) {
var newObj = {};
for (let i of Object.keys(o)) {
let ret = mapperFn( {v: o[i], i, o} );
if (typeof ret == "object" && !Array.isArray( ret )) {
Object.assign( newObj, ret );
}
else {
newObj[i] = ret;
}
}
return newObj;
}
function ap({ fns = [], arr = [] }) {
var newArr = [];
if (fns.length == 0) {
fns = [identity];
}
if (fns.length == 1) {
return map( {fn: fns[0], arr} );
}
for (let fn of fns) {
newArr = newArr.concat( map( {fn, arr} ) );
}
return newArr;
}
function stdAp(fns = [], arr = []) {
var newArr = [];
if (fns.length == 0) {
fns = [publicAPI.std.identity];
}
if (fns.length == 1) {
return publicAPI.std.map( fns[0], arr );
}
for (let fn of fns) {
newArr = newArr.concat( publicAPI.std.map( fn, arr ) );
}
return newArr;
}
function reduce({ fn: reducerFn, v: initialValue, arr = [] }) {
var origArr = arr;
var i = 0;
if (initialValue === undefined && arr.length > 0) {
initialValue = arr[0];
arr = arr.slice( 1 );
i++;
}
for (let v of arr) {
initialValue = reducerFn( {acc: initialValue, v, i: i++, arr: origArr} );
}
return initialValue;
}
function reduceObj({ fn: reducerFn, v: initialValue, o = {} }) {
var keys = Object.keys( o );
if (initialValue === undefined && keys.length > 0) {
initialValue = o[keys[0]];
keys = keys.slice( 1 );
}
for (let i of keys) {
initialValue = reducerFn( {acc: initialValue, v: o[i], i, o} );
}
return initialValue;
}
function reduceRight({ fn: reducerFn, v: initialValue, arr = [] }) {
var origArr = arr;
var idx = arr.length - 1;
if (initialValue === undefined && arr.length > 0) {
initialValue = arr[idx];
arr = arr.slice( 0, idx );
idx--;
}
for (let i = arr.length - 1; i >= 0; i--) {
initialValue = reducerFn( {acc: initialValue, v: arr[i], i: idx--, arr: origArr} );
}
return initialValue;
}
function flatten({ v: arr = [], n: depth = Infinity }) {
depth = Number( depth );
var list = [];
for (let v of arr) {
list = list.concat(
depth > 0 ?
(depth > 1 && Array.isArray( v ) ?
flatten( {v, n: depth - 1} ) :
v
) :
[v]
);
}
return list;
}
function zip({ arr1 = [], arr2 = [] }) {
var zipped = [];
var i1 = 0;
var i2 = 0;
while (i1 < arr1.length && i2 < arr2.length) {
zipped.push( [arr1[i1++], arr2[i2++]] );
}
return zipped;
}
function trampoline({ fn }) {
return function trampolined(...args) {
var result = fn( ...args );
while (typeof result == "function") {
result = result();
}
return result;
};
}
function transduce({ fn: transducer, co: combinationFn, v: initialValue, arr = [] }) {
var reducer = transducer( {v: combinationFn} );
return reduce( {fn: reducer, v: initialValue, arr} );
}
function stdTransduce(transducer,combinationFn,initialValue,arr = []) {
var reducer = transducer( combinationFn );
return publicAPI.std.reduce( reducer, initialValue, arr );
}
function into({ fn: transducer, v: initialValue, arr = [] }) {
var combinationFn =
typeof initialValue == "string" ? strConcat :
typeof initialValue == "number" ? numericAdd :
typeof initialValue == "boolean" ? booleanAnd :
Array.isArray( initialValue ) ? arrayPush :
publicAPI.transducers.default;
return transduce( {fn: transducer, co: combinationFn, v: initialValue, arr} );
}
function stdInto(transducer,initialValue,arr = []) {
var combinationFn =
typeof initialValue == "string" ? stdStrConcat :
typeof initialValue == "number" ? stdNumericAdd :
typeof initialValue == "boolean" ? stdBooleanAnd :
Array.isArray( initialValue ) ? stdArrayPush :
publicAPI.std.transducers.default;
return stdTransduce( transducer, combinationFn, initialValue, arr );
}
function transducerMap(argsObj) {
var { fn: mapperFn, v: combinationFn } = argsObj;
// still waiting on the combination function?
if (!_hasProp( argsObj, "v" ) || !combinationFn) {
// Note: the combination function is usually a composed
// function, so we expect the argument by itself,
// not wrapped in an object
return function curried({ v }){
return transducerMap( {fn: mapperFn, v} );
};
}
return function reducer({ acc, v }){
return combinationFn( {acc, v: mapperFn( {v} )} );
};
}
function stdTransducerMap(mapperFn,combinationFn) {
return function reducer(acc,v){
return combinationFn( acc, mapperFn( v ) );
};
}
function transducerFilter(argsObj) {
var { fn: predicateFn, v: combinationFn } = argsObj;
// still waiting on the combination function?
if (!_hasProp( argsObj, "v" ) || !combinationFn) {
// Note: the combination function is usually a composed
// function, so we expect the argument by itself,
// not wrapped in an object
return function curried({ v }){
return transducerFilter( {fn: predicateFn, v} );
};
}
return function reducer({ acc, v } = {}){
if (predicateFn( {v} )) {
return combinationFn( {acc, v} );
}
return acc;
};
}
function stdTransducerFilter(predicateFn,combinationFn) {
return function reducer(acc,v){
if (predicateFn( v )) {
return combinationFn( acc, v );
}
return acc;
};
}
function strConcat({ acc, v }) {
return String( acc ) + v;
}
function stdStrConcat(acc,v) {
return String( acc ) + v;
}
function arrayPush({ acc, v }) {
acc.push( v );
return acc;
}
function stdArrayPush(acc,v) {
acc.push( v );
return acc;
}
function numericAdd({ acc, v }) {
return (+acc) + (+v);
}
function stdNumericAdd(acc,v) {
return (+acc) + (+v);
}
function booleanAnd({ acc, v }) {
return !!acc && !!v;
}
function stdBooleanAnd(acc,v) {
return !!acc && !!v;
}
function booleanOr({ acc, v }) {
return !!acc || !!v;
}
function stdBooleanOr(acc,v) {
return !!acc || !!v;
}
function stdFlip(fn) {
return function flipped(arg1,arg2,...args){
return fn( arg2, arg1, ...args );
};
}
function stdReverseArgs(fn) {
return function reversed(...args){
return fn( ...args.reverse() );
};
}
function head({ v = [] }) {
if (v && (typeof v == "object" || typeof v == "string")) {
return v[0];
}
return v;
}
function tail({ v = [] }) {
if (v && (typeof v == "object" || typeof v == "string")) {
if (typeof v.slice == "function") {
return v.slice( 1 );
}
else {
let props = Object.keys( v ).filter( k => k != "0" );
return pick( {v, props} );
}
}
return v;
}
function take({ v = [], n = 1}) {
if (
v &&
(typeof v == "object" || typeof v == "string") &&
typeof v.slice == "function"
) {
return v.slice( 0, n );
}
return [];
}
// adapted from: https://github.com/caiogondim/fast-memoize.js
function memoize({ fn, n = fn.length }) {
var cache = {};
return Number( n ) > 1 ? memoizedMultipleArgs : memoizedSingleArg;
// *********************
function memoizedSingleArg(arg,...otherArgs) {
var hash =
// arg is a primitive?
(
arg == null ||
!(typeof arg == "object" || typeof arg == "function")
) ?
arg :
JSON.stringify( arg );
return (hash in cache) ?
cache[hash] :
(cache[hash] = fn( arg, ...otherArgs ));
}
function memoizedMultipleArgs(...args) {
var arg = args[0];
var hash =
// only one argument?
args.length == 1 &&
// arg is a primitive?
(
arg == null ||
!(typeof arg == "object" || typeof arg == "function")
) ?
arg :
JSON.stringify( args );
return (hash in cache) ?
cache[hash] :
(cache[hash] = fn( ...args ));
}
}
function remap({ fn, args = {}}) {
var props = {};
// transpose `args` from `target: source` to
// `source: target` for `reassoc(..)` to use
for (let prop of Object.keys( args )) {
props[args[prop]] = prop;
}
return function remapped(argsObj){
return fn( reassoc( {v: argsObj, props} ) );
};
}
// ***************************************
// Private
function _setMethodAlias(origName,aliasName) {
publicAPI[aliasName] = publicAPI[origName];
publicAPI.std[aliasName] = publicAPI.std[origName];
}
function _applyFnProp(fn,props) {
return function fnApplied(argsObj){
argsObj = Object.assign( {}, argsObj );
argsObj.fn = apply( {fn: argsObj.fn, props} );
return fn( argsObj );
};
}
function _hasProp(obj,prop) {
return Object.hasOwnProperty.call( obj, prop );
}
});