You can find all the code in this post at repo Github.
Function related challenges
Arguments & parameters
/**
* @param {Function} fn
* @return {number}
*/
function FunctionLength(fn) {
return fn.length;
}
// Usage example
function myFunction(a, b, c) {
console.log(a, b, c);
}
console.log(FunctionLength(myFunction)); // => 3
/**
* @param {...any} args
* @return {number}
*/
function numOfArguments(...args) {
// return args.length;
return arguments.length;
}
// Usage example
console.log(numOfArguments(1, 2, 3, 4, 5)); // => 5
console.log(numOfArguments()); // => 0
Compose
/**
* @param {...Functions} fns
* @return Function
*/
function compose(...fns) {
return function (x) {
let result = x;
for (const fn of fns.reverse()) {
result = fn(result);
}
return result;
};
}
// Usage example
const add1 = (num) => num + 1;
const double = (num) => num * 2;
const subtract10 = (num) => num - 10;
const composedFn = compose(subtract10, double, add1);
console.log(composedFn(3)); // (3 + 1) * 2 - 10 => -2
Currying
/**
* @param {Function} fn
* @return {Function}
*/
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return curried.bind(this, ...args);
};
}
// Usage example
// single parameter case
function add(a, b) {
return a + b;
}
const curriedAdd = curry(add);
console.log(curriedAdd(3)(4)); // => 7
const alreadyAddedThree = curriedAdd(3);
console.log(alreadyAddedThree(4)); // => 7
// fixed parameters case
function addTwo(a, b) {
return a + b;
}
const curriedAddTwo = curry(addTwo);
console.log(curriedAddTwo(3, 4)); // => 7
console.log(curriedAddTwo(3)(4)); // => 7
const alreadyAddedThreeB = curriedAdd(3);
console.log(alreadyAddedThreeB(4)); // => 7
//-------------------------------------------
/**
* @param {Function} fn
* @return {Function}
*/
function curry(fn) {
return function curried(...args) {
const bindFn = curried.bind(this, ...args);
bindFn[Symbol.toPrimitive] = () => fn.call(this, ...args);
return bindFn;
};
}
// Usage example
// non-fixed parameters case
function multiply(...numbers) {
return numbers.reduce((a, b) => a * b, 1);
}
const curriedMultiply = curry(multiply);
const multiplyByThree = curriedMultiply(3);
console.log(multiplyByThree); // => 3
console.log(multiplyByThree(4)); // => 12
const multiplyByFifteen = multiplyByThree(5);
console.log(multiplyByFifteen); // => 15
console.log(multiplyByFifteen(2)); // => 30
console.log(curriedMultiply(1)(2)(3)(4)); // => 24
console.log(curriedMultiply(1, 2, 3, 4)); // => 24
Memo
/**
* @param {Function} func
* @return {Function}
*/
function memoize(fn) {
const cache = new Map();
return function (arg) {
if (cache.has(arg)) {
return cache.get(arg);
}
const result = fn.call(this, arg);
cache.set(arg, result);
return result;
};
}
// Usage example
function expensiveFunction(n) {
console.log("Computing...");
return n * 2;
}
// Create a memoized version of the function.
const memoizedExpensiveFunction = memoize(expensiveFunction);
// First call (computes and caches the result).
console.log(memoizedExpensiveFunction(5)); // => Computing... 10
// Second call with the same argument (returns the cached result).
console.log(memoizedExpensiveFunction(5)); // => 10
// Third call with a different argument (computes and caches the new result).
console.log(memoizedExpensiveFunction(10)); // => Computing... 20
// Fourth call with the same argument as the third call (returns the cached result).
console.log(memoizedExpensiveFunction(10)); // => 20
// ----------------------------------------
// When parameters could be array
/**
* @param {Function} fn
* @return {Function}
*/
function memoize(fn) {
const cache = new Map();
return function (...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.call(this, ...args);
cache.set(key, result);
return result;
};
}
// Usage example
function expensiveMul(a, b) {
console.log("Computing...");
return a * b;
}
// Create a memoized version of the function.
const memoizedExpensiveMul = memoize(expensiveMul);
// First call (computes and caches the result).
console.log(memoizedExpensiveMul(3, 7)); // => Computing... 21
// Second call with the same argument (returns the cached result).
console.log(memoizedExpensiveMul(3, 7)); // => 21
// Third call with a different argument (computes and caches the new result).
console.log(memoizedExpensiveMul(5, 8)); // => Computing... 40
// Fourth call with the same argument as the third call (returns the cached result).
console.log(memoizedExpensiveMul(5, 8)); // => 40
Partial
/**
* @param {Function} fn
* @param {any[]} args
* @returns {Function}
*/
function partial(fn, ...args) {
return function (...restArgs) {
const copyArgs = args.map((arg) => {
return arg === partial.placeholder ? restArgs.shift() : arg;
});
return fn.call(this, ...copyArgs, ...restArgs);
};
}
partial.placeholder = Symbol();
// Usage example
const func = (...args) => args;
const func123 = partial(func, 1, 2, 3);
console.log(func123(4)); // => [1, 2, 3, 4]
Reference
- GreatFrontEnd
- The arguments object - MDN
- Parameter - MDN
- Function composition (computer science) - Wikipedia.org
- 11. what is Composition? create a pipe() - BFE.dev
- 1. implement curry() - BFE.dev
- 2. implement curry() with placeholder support - BFE.dev
- Currying - Wikipedia.org
- 14. Implement a general memoization function -
memo()
- BFE.dev - 122. implement memoizeOne() - BFE.dev
- Memoization - Wikipedia.org
- Partial application - Wikipedia.org
- 139. implement _.partial() - BFE.dev
Top comments (0)