JS Polyfills - Part 6 Curry, Memoise and Generator Functions
Tags: webdev, javascript, jspollyfill, codesandbox
Published: 2023-02-10 13:57:31

<link rel="canonical" href="https://dev.to/uttarasriya/js-polyfills-part-6-curry-memoise-and-generator-functions-1d71" />
**Github Code:** [JS Polyfills](https://github.com/uttara-sriya/JS-Polyfills)

**16. Curry**
<u>Currying:</u> Transformation of function with multiple parameters to a sequence of single parameters is Currying. Currying just transforms the function, it will not call the function. Partial functions can be easily generated using currying.
- <u>Function</u>: `Curry(fn)`
- <u>Description</u>: A functional programming technique for transforming multiple parameter function to a multiple single parameter functions.
- <u>Code Sandbox:<u> [Curry](https://codesandbox.io/s/recursing-frog-g209xn)

```javascript
//A functional programming technique for transforming multiple parameter function to a multiple single parameter functions.
//In this example, the curry function takes a function fn as an argument and returns a new curried function curried. The curried function takes a variable number of arguments, stored in the args array. If the number of arguments passed to curried is equal to or greater than the number of arguments expected by fn, fn is called with the apply method, passing in the args array. If the number of arguments passed to curried is less than the number of arguments expected by fn, the curried function returns a new function that takes the remaining arguments and concatenates them to the args array. This allows us to partially apply the arguments to the function and return a new function that takes the remaining arguments. The returned function can be called multiple times until all the arguments have been provided, at which point fn is finally executed.
function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    }
    return function (...args2) {
      return curried.apply(this, args.concat(args2));
    };
  };
}

// Usage example
function add(a, b, c) {
  return a + b + c;
}

const curriedAdd = curry(add);
const add5 = curriedAdd(5);

console.log(add5(10)(15));
// Output: 30


```
**17. Memoise**
<u>Memoization:</u> A functional programming optimization technique with a top-down, depth-first approach for caching/storing previous value/computation so that the computed value is never executed again when necessary.
- <u>Function</u>: `Memoize(fn)`
- <u>Description</u>: Memoize function takes another function fn as its argument and returns a new function that wraps fn
- <u>Code Sandbox:<u> [Memoize](https://codesandbox.io/s/keen-proskuriakova-toq743)

```javascript
//This function takes another function fn as its argument and returns a new function that wraps fn. The returned function caches the results of previous calls to fn using a simple JavaScript object cache. The cache key is generated by JSON.stringifying the arguments passed to the function. If a matching key is found in the cache, the cached result is returned. Otherwise, fn is called and its result is stored in the cache before being returned.
function memoize(fn) {
  let cache = {};
  return function (...args) {
    let key = JSON.stringify(args);
    if (cache[key]) {
      return cache[key];
    }
    let result = fn.apply(this, args);
    cache[key] = result;
    return result;
  };
}

// A function to calculate the factorial of a number
function factorial(n) {
  if (n === 1) return 1;
  return n * factorial(n - 1);
}

// Memoized version of the factorial function
let memoizedFactorial = memoize(factorial);

// Calculating factorials
console.log(memoizedFactorial(5)); // 120
console.log(memoizedFactorial(5)); // 120 (returned from cache)
console.log(memoizedFactorial(6)); // 720

```

**18. Generator Functions**
<u>Generator Function:</u> Generator functions can be exited and reentered with saved context. These functions can mitigate callback hell and inversion of control. When generator functions are called, a generator object will be returned. 
<u>yield</u> When the iterator's next() method is called, the generator function's body is executed until the first yield expression, which specifies the value to be returned from the iterator or, with yield*, delegates to another generator function.
<u>next</u> The next() method returns an object with a value property containing the yielded value and a done property which indicates whether the generator has yielded its last value, as a boolean. 
- <u>Function</u>: `GeneratorFunction(fn* () { })`
- <u>Description</u>:Generator will return a function or nothing.
- <u>Code Sandbox:<u> [Generator Function](https://codesandbox.io/s/sleepy-thompson-2q01e0)

```javascript
//This polyfill checks if the Symbol.iterator property is a function. If it's not, it defines the GeneratorFunction constructor, which is the constructor of a generator function, and sets its Symbol.iterator property to a function that returns an object with a next method. This next method simply returns an object with value set to undefined and done set to true, which is the expected behavior for an iterator that has completed.
(function () {
  if (typeof Symbol.iterator !== 'function') {
    let GeneratorFunction = (function* () { }).constructor;
    GeneratorFunction.prototype[Symbol.iterator] = function () {
      return {
        next: function () {
          return { value: void 0, done: true };
        }
      };
    };
  }
})();

```
Sources: [MDN](https://developer.mozilla.org/en-US/)

Keep Learning!