Skip to content

Instantly share code, notes, and snippets.

@brianboyko

brianboyko/functional.js

Last active Oct 19, 2017
Embed
What would you like to do?
Functional Tools
// Takes a function and additional arguments to be applied, and returns
// a new function with those provided arguments already partially applied.
export const curry = (f, ...curriedArgs) => (...newArgs) =>
f.apply(null, curriedArgs.concat(newArgs));
// Allows to iterate functions over a variable.
export const Identity = value => ({
value,
map: f => Identity(f(value))
});
// a clone of array.splice, but which returns a new array, instead
// of mutating the current array (helps to reduce errors.)
export const shank = (array, start, delCount, ...concatables) =>
array
.slice(0, start)
.concat(concatables)
.concat(array.slice(start + delCount));
// Returns a copy of the value of the array (instead of a reference to the same array);
export const clone = object => Object.assign({}, object);
// Takes and object and an array of keys, returns a copy of the object *excluding*
// the terms defined.
export const omit = (o, terms) =>
Object.keys(o)
.filter(key => !terms.includes(key))
.reduce((pv, k) => Object.assign({}, pv, { [k]: o[k] }), {});
// Takes an object and an array of keys, returns a copy of the object *including only*
// the terms defined.
export const pick = (o, terms) =>
terms.reduce((pv, term) => Object.assign({}, pv, { [term]: o[term] }), {});
// determines if two items are 'deeply equal" - most often used to determine if
// one object's value and structure is identical to another.
export const isEqual = (a, b) => {
if (typeof a !== typeof b) {
return false;
}
if (Array.isArray(a) && Array.isArray(b)) {
return a.length === b.length && a.every((el, i) => isEqual(a[i], b[i]));
}
if (typeof a === "object") {
return (
isEqual(Object.keys(a).sort(), Object.keys(b).sort()) &&
Object.keys(a).every(k => isEqual(a[k], b[k]))
);
}
// primitive checks. Will also determine if two function definition points
// to the same memory space.
if (a === b) {
return true;
}
return false;
};
// takes an origin (an object), a pathway (string or array), and a defaultValue;
// get() will parse the pathway if it is a string into an array of strings,
// then it will sequentially work down the array's properties
// if any property in the chain is undefined, instead of returning an error,
// it will instead return the defaultValue provided.
export const get = (origin, pathway, defaultValue) => {
if (typeof pathway === "string") {
return get(origin, pathway.split("."), defaultValue);
}
if (!Array.isArray(pathway)) {
return defaultValue;
}
if (pathway.length === 0) {
return origin;
}
pathway = pathway.reduce((pv, el) => pv.concat(el.split(".")), []);
if (!origin[pathway[0]]) {
return defaultValue;
}
return get(origin[pathway[0]], pathway.slice(1), defaultValue);
};
// Creates an array of numbers (positive and/or negative) progressing from start up to, but not including, end.
// A step of -1 is used if a negative start is specified without an end or step. If end is not specified, it's set to start with start then set to 0.
export const range = (start = 0, end, step) => {
if (step === 0 || (start < end && step < 0) || (start > end && step > 0)) {
return range(start, end).map(el => start);
}
if (end === undefined) {
end = start;
start = 0;
}
if (!step) {
step = start < end ? 1 : -1;
}
let result = [];
if (start < end) {
while (start < end) {
result.push(start);
start += step;
}
}
if (start > end) {
while (start > end) {
result.push(start);
start += step;
}
}
return result;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.