Return the first item in an array
const head = ([x]) => x;
Return all but the first item in an array.
const tail = ([, ...xs]) => xs;
const isDefined = x => typeof x !== 'undefined';
const isUndefined = x => !isDefined(x);
const copy = array => [...array];
const length = ([x, ...xs], len = 0) => isDefined(x) ? length(xs, len + 1) : len;
const reverse = ([x, ...xs]) => isDefined(x) ? [...reverse(xs), x] : [];
Returns a new array of first n items
const first = ([x, ...xs], n = 1) => isDefined(x) && n ? [x, ...first(xs, n - 1)] : [];
Returns a new array of last n items
const last = (xs, n = 1) => reverse(first(reverse(xs), n));
Returns a new array with inserted value at given index
const slice = ([x, ...xs], i, y, curr = 0) => isDefined(x)
? curr === i
? [y, x, ...slice(xs, i, y, curr + 1)]
: [x, ...slice(xs, i, y, curr + 1)]
: [];
const isArray = x => Array.isArray(x);
Combines nested arrays into a single array
const flatten = ([x, ...xs]) => isDefined(x)
? isArray(x) ? [...flatten(x), ...flatten(xs)] : [x, ...flatten(xs)]
: [];
Return a new array with 2 items swapped based on their index
const swap = (a, i, j) => (
map(a, (x,y) => {
if(y === i) return a[j]
if(y === j) return a[i]
return x
})
);
const map = ([x, ...xs], fn) => isDefined(x) ? [fn(x), ...map(xs, fn)] : [];
const filter = ([x, ...xs], fn) => isDefined(x)
? fn(x)
? [x, ...filter(xs, fn)] : [...filter(xs, fn)]
: [];
The opposite of filter, returns an array that does not pass the filter function
const reject = ([x, ...xs], fn) => {
if (isUndefined(x)) return []
if (!fn(x)) {
return [x, ...reject(xs, fn)]
} else {
return [...reject(xs, fn)]
}
};
Splits an array into two arrays. One whose items pass a filter function and one whose items fail
const partition = (xs, fn) => [filter(xs, fn), reject(xs, fn)];
applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value
const reduce = ([x, ...xs], fn, memo, i = 0) => isDefined(x)
? reduce(xs, fn, fn(memo, x, i), i + 1) : memo;
const reduceRight = (xs, fn, memo) => reduce(reverse(xs), fn, memo);
Partially apply a function by filling in any number of its arguments
const partial = (fn, ...args) => (...newArgs) => fn(...args, ...newArgs);
const spreadArg = (fn) => (...args) => fn(args);
const reverseArgs = (fn) => (...args) => fn(...reverse(args));
Extract property value from array. Useful when combined with the map function
const pluck = (key, object) => object[key];
Each function consumes the return value of the function that came before
const flow = (...args) => init => reduce(args, (memo, fn) => fn(memo), init);
The same as flow, but arguments are applied in the reverse order
const compose = (...args) => flow(...reverse(args))
Return the smallest number in an array
const min = ([x, ...xs], result = Infinity) => isDefined(x)
? x < result
? min(xs, x)
: result
: result;
Return the largest number in an array
const max = ([x, ...xs], result = -Infinity) => isDefined(x)
? x > result
? max(xs, x)
: max(xs, result)
: result;
Returns the factorial of a number
const factorial = (x, acum = 1) => x ? factorial(x - 1, x * acum) : acum;
Returns the Fibonacci number at the given place
const fib = x => x > 2 ? fib(x - 1) + fib(x - 2) : 1;
Sort an array from smallest to largest
const quicksort = (xs) => length(xs)
? flatten([
quicksort(filter(tail(xs), x => x <= head(xs))),
head(xs),
quicksort(filter(tail(xs), x => x > head(xs)))
])
: [];
const reduce = ([x, ...xs], f, memo, i = 0) => isDefined(x)
? reduce(xs, f, f(memo, x, i), i + 1) : memo;
const reverse = xs => reduce(xs, (memo, x) => [x, ...memo], []);
const length = xs => reduce(xs, (memo, x) => memo + 1, 0);
const map = (xs, fn) => reduce(xs, (memo, x) => [...memo, fn(x)], []);
const filter = (xs, fn) => reduce(xs, (memo, x) => fn(x)
? [...memo, x] : [...memo], []);
const reject = (xs, fn) => reduce(xs, (memo, x) => fn(x)
? [...memo] : [...memo, x], []);
const first = (xs, n) => reduce(xs, (memo, x, i) => i < n
? [...memo, x] : [...memo], []);
const last = (xs, n) => reduce(xs, (memo, x, i) => i >= (length(xs) - n)
? [...memo, x] : [...memo], []);
const merge = spreadArg(xs => reduce(xs, (memo, x) => [...memo, ...x], []));
const flatten = xs => reduce(xs, (memo, x) => x
? isArray(x) ? [...memo, ...flatten(x)] : [...memo, x] : [], []);
const add = spreadArg(([x, ...xs]) => reduce(xs, (memo, y) => memo + y, x));
const divide = spreadArg(([x, ...xs]) => reduce(xs, (memo, y) => memo / y, x));
const multiply = spreadArg(([x, ...xs]) => reduce(xs, (memo, y) => memo * y, x));