luizbills
1/13/2016 - 1:05 AM

A set of pure and immutable ES2015 functions aimed to make functional JavaScript more idiomatic.

A set of pure and immutable ES2015 functions aimed to make functional JavaScript more idiomatic.

// array utils
// =================================================================================================

const combine = (...arrays) => [].concat(...arrays);

const compact = arr => arr.filter(Boolean);

const contains = (() => Array.prototype.includes
  ? (arr, value) => arr.includes(value)
  : (arr, value) => arr.some(el => el === value)
)();

const difference = (arr, ...others) => {
  var combined = [].concat(...others)
  return arr.filter(el => !combined.some(exclude => el === exclude))
};

const head = arr => arr[0];

const initial = arr => arr.slice(0, -1);

const intersection = (...arrays) =>
  [...Set([].concat(...arrays))].filter(toFind =>
    arrays.every(arr => arr.some(el => el === toFind))
  );

const last = arr => arr.slice(-1)[0];

const sortedIndex = (arr, value) =>
  [value].concat(arr).sort().indexOf(value);

const tail = arr => arr.slice(1);

const toArray = (() => Array.from ? Array.from : obj => [].slice.call(obj))();

const union = (...arrays) => [...Set([].concat(...arrays))];

const unique = arr => [...Set(arr)];

const without = (arr, ...values) =>
  arr.filter(el => !values.some(exclude => el === exclude));


// object utils
// =================================================================================================

const getValues = obj => Object.keys(obj).map(key => obj[key]);

const merge = (() => {
  const extend = Object.assign ? Object.assign : (target, ...sources) => {
    sources.forEach(source =>
      Object.keys(source).forEach(prop => target[prop] = source[prop])
    );
    return target;
  };
  return (...objects) => extend({}, ...objects);
})();

const toMap = (() => {
  const convert = obj => new Map(Object.keys(obj).map(key => [key, obj[key]]));
  return obj => obj instanceof Map ? obj : convert(obj);
})();


// math
// =================================================================================================

const min = arr => Math.min(...arr);

const max = arr => Math.max(...arr);

const sum = arr => arr.reduce((a, b) => a + b);

const product = arr => arr.reduce((a, b) => a * b);


// function decorators
// =================================================================================================

const not = fn => (...args) => !fn(...args);

const maybe = fn =>
  (...args) => {
    if (args.length < fn.length || args.some(arg => arg == null)) return;
    return fn(...args);
  };

const once = fn => {
  var done = false;
  return (...args) => {
    if (done) return;
    done = true;
    fn(...args);
  };
};

const curry = fn => {
  const arity = fn.length;
  const curried = (...args) =>
    args.length < arity ? (...more) => curried(...args, ...more) : fn(...args);
  return curried;
};

const pipeline = (...funcs) =>
  value => funcs.reduce((a, b) => b(a), value);