pure functions, currifications, combinatorial functions

pure functions

define
1. same input, same output.
2. there will be no side effects during execution.

const letters = ['a', 'b', 'c'];
// pure function
letters.slice(1);
console.log(letters); // [ 'a', 'b', 'c' ]
// produce side effects, impure functions
letters.splice(1);
console.log(letters); // [ 'a' ]

currieization

defining a function that passes
only a subset of the arguments to the function and returns a function that receives the remaining arguments is curriization

let the function have a single responsibility

function add(x, y, z) {
  x = x + 2;
  y = y * 2;
  z = z * z;
  return x + y + z;
}

console.log(add(10, 20, 30));

// Currying
function sum(x) {
  x = x + 2;
  return function (y) {
    y = y * 2;
    return function (z) {
      z = z * z;
      return x + y + z;
    };
  };
}

console.log(sum(10)(20)(30));

reuse of code

const makeAdder = count => {
  return num => {
    return count + num;
  };
};

const adder5 = makeAdder(5);
console.log(adder5(10)); // 15
console.log(adder5(20)); // 25

implementation of the currie-ization function

// Takes a function and returns a curried function
function myCurrying(fn) {
  function curried(...args) {
    // When the incoming parameters are less than the original function parameters
    if (args.length < fn.length) {
      // Returns a function to handle the remaining arguments
      return function (...args2) {
        // Remaining parameters, splicing existing parameters for recursion
        return curried.apply(this, args.concat(args2));
      };
    } else {
      // Call directly and bind this
      return fn.apply(this, args);
    }
  }

  return curried;
}

function add(num1, num2, num3) {
  console.log(this);
  return num1 + num2 + num3;
}

const newFn = myCurrying(add);
console.log(newFn.call('abc', 10, 20, 30));
console.log(newFn(10, 20)(30));
console.log(newFn(10)(20)(30));

combinatorial functions

definition multiple
functions need to be executed sequentially. combining these functions and executing them in turn is a combination of functions.

function double(num) {
  return num * 2;
}

function square(num) {
  return num ** 2;
}
// Suppose you need to execute double first
const res = square(double(10));
console.log(res);

// Simple implementation of composition function
function composeFn(fn1, fn2) {
  return function (count) {
    return fn2(fn1(count));
  };
}

const newFn = composeFn(double, square);
const res2 = newFn(20);
console.log(res2);

implementation of a universal combinatorial function

function add(num1, num2) {
  console.log(this);
  return num1 + num2;
}
function double(num) {
  console.log(this);
  return num * 2;
}
function square(num) {
  console.log(this);
  return num ** 2;
}

// Generic composition function implementation
function myCompose(...fns) {
  if (!fns.length) {
    throw new TypeError('The function type must be passed in');
  }
  for (let fn of fns) {
    if (typeof fn !== 'function') {
      throw new TypeError('The function type must be passed in');
    }
  }

  // Returns a function that is automatically executed sequentially
  function composeFn(...args) {
    // do it once
    let index = 0;
    let res = fns[index].apply(this, args);

    // Get the previous result and call the next function to get the new result
    while (++index < fns.length) {
      res = fns[index].call(this, res);
    }
    return res;
  }

  return composeFn;
}

const newFn = myCompose(add, double, square);
const res = newFn.call('call', 10, 20);
console.log(res);

Leave a Reply