/* // // # 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 // pipe: Runs functions from left to right. // compose: Runs functions from right to left. // identity: Returns whatever you give it as is. // curry: Converts a function to its curried form. // match: Creates a curried function to match a regular expression in a string. // replace: Creates a curried function to replace parts of a string. // filter: Curried array filtering. // map: Curried array mapping. // deepMap: Curried recursive mapping for nested arrays or matrices. 'use strict' const b = { /** * Composes functions from left to right. * Takes any number of functions as arguments and returns the result of applying them in sequence. * @param {...Function} args - The functions to be composed. * @returns {Function} - A function that applies the composed functions from left to right. */ pipe: (...args) => args.reduce((acc, el) => el(acc)), /** * 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.call(null, ...res)], args)[0], /** * A function that returns its input unmodified. * @param {*} x - The input value. * @returns {*} - The same input value. */ identity: x => x, /** * Converts a function into a curried function. * 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: (fn) => { const curried = (...args) => { if (args.length >= fn.length) return fn(...args) else return (...rest) => curried(...args, ...rest) } return curried }, /** * 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: () => b.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: () => b.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: () => b.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: () => b.curry((f, xs) => xs.map(f)), /** * Curried function that recursively maps a function over an array or matrix of any depth. * @returns {Function} - A curried function that takes a mapping function and a nested array, and returns the deeply mapped array. */ deepMap: () => b.curry(function deepMap(f, xs) { return Array.isArray(xs) ? xs.map((x) => deepMap(f, x)) : f(xs); }), }; // // pipe // const title = '10 Weird Facts About Dogs'; // const toLowerCase = (str) => str.toLowerCase(); // const addHyphens = (str) => str.replace(/\s/g, '-'); // const reverseText = (str) => (str === '') ? '' : reverseText(str.substr(1)) + str.charAt(0); // const slug = b.pipe(title, toLowerCase, addHyphens, reverseText); // console.log('pipe ', slug); // // compose // const toUpperCase = x => x.toUpperCase(); // const exclaim = x => `${x}!`; // const shout = b.compose(exclaim, toUpperCase); // const ret = shout('send in the clowns'); // "SEND IN THE CLOWNS!" // console.log('compose ', ret); // // curry family // const hasLetterR = b.match(/r/g); // const r1 = hasLetterR('hello world'); // const r2 = hasLetterR('just j and s and t etc'); // const r3 = b.filter(hasLetterR, ['rock and roll', 'smooth jazz']); // const noVowels = b.replace(/[aeiou]/ig); // const censored = noVowels('*'); // const r4 = censored('Chocolate Rain'); // console.log('curry ', r1, r2, r3, r4);