/*
//
// # The Witch in the Glass
//
// My mother says I must not pass
// Too near that glass;
// She is afraid that I will see
// A little witch that looks like me,
// With a red, red mouth to whisper low
// The very thing I should not know!
//
// Alack for all your mother's care!
// A bird of the air,
// A wistful wind, or (I suppose
// Sent by some hapless boy) a rose,
// With breath too sweet, will whisper low
// The very thing you should not know!
//
// - Sarah Morgan Bryan Piatt
//
*/
// b is for useful stuff
// curry: Converts a function to its curried form, allowing for partial application.
// pipe: Runs functions from left to right, passing the result of one to the next.
// compose: Runs functions from right to left, passing the result of one to the next.
// identity: Returns whatever you give it as is. Useful for composition...sometimes.
// match: Creates a curried function to match a regular expression in a string.
// replace: Creates a curried function to replace parts of a string, based on a regex or substring.
// filter: Curried array filtering by a predicate function.
// map: Curried array mapping.
// deepMap: Curried recursive mapping for nested arrays or matrices, of any shape.
'use strict'
const b = {
/**
* Converts a function into a curried function, allowing for partial application.
* A curried function can be partially applied and will return a new function until all arguments are provided.
* @param {Function} fn - The function to curry.
* @returns {Function} - The curried function.
*/
curry: function (fn) {
const curried = (...args) => {
if (args.length >= fn.length)
return fn(...args)
else
return (...rest) => curried(...args, ...rest)
}
return curried
},
/**
* Composes functions from left to right.
* Takes any number of functions as arguments and returns a function that applies them in sequence to a supplied value.
* @param {...Function} fns - The functions to be composed.
* @returns {Function} - A function that takes an initial value and applies the composed functions from left to right.
*/
pipe: (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value),
/**
* Composes functions from right to left.
* Takes any number of functions as arguments and returns a function that applies them in sequence from right to left.
* @param {...Function} fns - The functions to be composed.
* @returns {Function} - A function that applies the composed functions from right to left.
*/
compose: (...fns) => (...args) => fns.reduceRight((res, fn) => fn(...[].concat(res)), args),
/**
* A function that returns its input totally and completely unchanged.
* @param {*} x - The input value.
* @returns {*} - The same input value.
*/
identity: x => x,
/**
* Curried function that matches a regular expression against a string.
* @returns {Function} - A curried function that takes a regex and a string and returns the match result.
*/
match: function () {
return this.curry((what, s) => s.match(what));
},
/**
* Curried function that replaces parts of a string based on a regex or substring.
* @returns {Function} - A curried function that takes a regex or substring, a replacement, and a string, and returns the replaced string.
*/
replace: function () {
return this.curry((what, replacement, s) => s.replace(what, replacement));
},
/**
* Curried function that filters an array based on a predicate function.
* @returns {Function} - A curried function that takes a predicate function and an array, and returns the filtered array.
*/
filter: function () {
return this.curry((f, xs) => xs.filter(f));
},
/**
* Curried function that maps a function over an array.
* @returns {Function} - A curried function that takes a mapping function and an array, and returns the mapped array.
*/
map: function () {
return this.curry((f, xs) => xs.map(f));
},
/**
* Curried function that recursively maps a function over an array or matrix of any shape.
* @returns {Function} - A curried function that takes a mapping function and a nested array, and returns the deeply mapped array.
*/
deepMap: function () {
return this.curry(function deepMap(f, xs) {
return Array.isArray(xs)
? xs.map((x) => deepMap(f, x))
: f(xs);
});
},
};
if (typeof module !== 'undefined' && module.exports) {
module.exports = b;
}