Functional programming

What is functional programming?

Functional programming (FP) : Refers to a programming paradigm, often referred to as object-oriented programming, and procedural programming.

Object orientation is the abstraction of objects in the real world into objects in the program world.

Functional programming abstracts the relationships between things into the program world, the process of computing. The function in functional programming is not the function in the program, but the function in mathematics is the mapping.

The benefits are function reuse and function reorganization.

Higher-order functions:

What is a higher-order function?

Functions that take arguments or return values are higher-order functions.

Function as an example of a return value

function once(fn) {
  let done = false;
  return function () {
    if(! done) { done =true;
      fn.apply(this.arguments); // You can use the apply method to specify the calling environment}}; }let fn = once(function (money) {
  console.log(` paid${money}Yuan `);
});

fn(5);
Copy the code

Higher-order functions are used for abstraction, allowing us to focus only on the goal of implementation

// Implement the map method using higher-order functions
const map = function (array, fn) {
  let newResult = [];
  for (let value of array) {
    // The difference between for of and for in loops
    newResult.push(fn(value));
  }
  return newResult;
};
let arr = [1.2.3.4.5];
let newArr = map(arr, function (item) {
  return item * item;
});


Copy the code
// Use higher-order functions to implement every
const every = function (array, fn) {
  let isTorF = true;
  for (let value of array) {
    if (fn(value)) {
      isTorF = false;
      if(! result){// Break out of the loop when errors occur
          break}}}return isTorF;
};

let arr = [1.2.3.4];
console.log(
  every(arr, function (item) {
    return item > 3; }));Copy the code
// Higher-order functions implement some methods
const some = function (array, fn) {
  let isTorF = false;
  for (let value of array) {
    if (fn(value)) {
      isTorF = true;
      if (isTorF) {
        break; }}}return isTorF;
};

let arr = [1.2.3.4.5.6];

console.log(some(arr, function (value) {
  return value > 3;
}));
Copy the code
  • There is a difference between a for of and a for in loop

For in can only get the key name but not the key value, and for of can get the key value

Closure:

A closure is a function that calls inside a function in a scope and accesses members of that function scope. Functions are placed on an execution stack during execution and removed after completion, but scope members on the heap cannot be released because they are referenced externally.

Pure functions:

Concept: The same input always produces the same output, with no observable side effects.

The side effect is that the function cannot guarantee the same output depending on the external state

let a = 20
function(b){ // Every time input b=30, there is no guarantee of the same output when a is changed to another function, i.e. side effect
  return a>b
}
// Source of side effects: All external interactions can produce side effects, but they should be kept under control and not completely prohibited.
Copy the code

For example, slice is a pure function, but splice is not. The result is the same multiple times.

Pure function benefits, cacheable, easy to test.

function area(r) { // Compute the circle area as a function
  console.log(123);
  return Math.PI * r * r;
}

function memorize(fn) { // Convert a function to a memory function
  let cache = {};
  return function () {
    let key = JSON.stringify(arguments);
    cache[key] = cache[key] || fn.apply(fn, arguments);
    return cache[key];
  };
}

let areaMemorize = memorize(area); // Remember the function that calculates the circle area
areaMemorize(2); / / 123
areaMemorize(2); // There is no print, the result is remembered, do not call area function recalculation
areaMemorize(3); / / 123
Copy the code

Lodash:

NPM install lodash //lodashCopy the code

Corey:

When a function has more than one argument, it is called by passing some of the arguments (these arguments never change).

It then returns a function that takes the remaining arguments and returns the result.

  • _.curry(func)
    • The func function creates a function that takes one or more func arguments, calls the func function if the arguments are satisfied, otherwise returns the function and waits for the rest of the arguments to be accepted
    • Parameters: functions that require currization
    • Return value: The currified function
const _ = require("lodash");

function sum(a, b, c) {
  return a + b + c;
}

let curried = _.curry(sum);

console.log(curried(1.2.3)); / / 6
console.log(curried(1.2) (3)); / / 6
Copy the code

Corrification principle:

// Explore principles from top to bottom
 function curry(func) {
  return function curried(. args) {// Currize returns the function
    // If the number of parameters is not enough, return the function
    if (args.length < func.length) {
      return function () {
        returncurried(... args.concat(Array.from(arguments)));
      };
    } else {
      // When the parameters are met, execute directly
      return func(...args);
    }
  };
}
Copy the code

Function combination:

That is, you combine the intermediate functions to make one function.

The function _.flowRight() in Lodash can be used for function combinations, noting that the order of execution is from right to left

const _ = require("lodash");

let reverse = (arr) = > arr.reverse();
let getFirst = (arr) = > arr[0];
let toUpper = (str) = > str.toUpperCase();

let fn = _.flowRight(toUpper, getFirst, reverse);
console.log(fn(["one"."two"."three"]));
Copy the code

Principle of combination function:

function flowRight(. args) {
  return function (value) {
    return args.reverse().reduce((acc, fn) = > {
      return fn(acc);
    }, value);
  };
}
Copy the code

Associative law:

let fn = flowRight(toUpper, flowRight(getFirst, reverse));
Copy the code

Debugging of composite functions:

Lodash fp module:

Because functional programming follows the principle of data lag function first, the functions in LoDash’s FP library provide these methods without modifying the LoDash functions. Let fp = require(‘lodash/fp’

The methods in LoDash are data-first and function lagged.

Point Free:

Point Free programming style is to define the process of data processing as a function independent of the composition operation, do not need to use the function representing the data, just need to synthesize the simple operation data together. It’s a combination of functions.

Functor:

Is a special container implemented using a normal object that has a map method that runs a function to manipulate values (deformation relationships).

class Container {
  static of(value) { // Use of static methods, not new, do not consider object-oriented
    return new Container(value);
  }
  constructor(value) { 
    this._value = value;
  }
  map(fn) { //map method, passing in a deformation function to transform the values in a container to another container
    return Container.of(fn(this._value));
  }
}

Container.of(5) // But if the value passed here is null, an error will be reported, in which case we need to handle the external null value
  .map((x) = > x + 2)
  .map((x) = > x * x);

Copy the code

MayBe functor.

In view of the programming error to do processing, transformed into can handle null value and undefined

class MayBe {
  static of(value) {
    // Use of static methods, not new, do not consider object-oriented
    return new MayBe(value);
  }
  constructor(value) {
    this._value = value;
  }
  map(fn) {
    //map method, passing in a deformation function to transform the values in a container to another container
    return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value));
  }
  isNothing() {
    return this._value === null || this._value === undefined; }}console.log(
  MayBe.of(null) // The null problem is resolved, but we do not know which step caused the null value problem
    .map((x) = > x + 2)
    .map((x) = > x * x)
);

Copy the code

Either functor:

If an exception occurs, the function becomes impure, so we use Either functor for exception handling

class Left { // Error handling
  static of(value) {
    return new Left(value);
  }
  constructor(value) {
    this._value = value;
  }
  map(fn) { // Return an error message
    return this; }}class Right { // Get it right
  static of(value) {
    return new Right(value);
  }
  constructor(value) {
    this._value = value;
  }
  map(fn) {
    return Right.of(fn(this._value)); }}function parseJSON(json) {
  try {
    return Right.of(JSON.parse(json));
  } catch (e) {
    return Left.of({ error: e.message }); }}let r = parseJSON({ name: "zs" }).map((x) = > x.name.toUpperCase());
console.log(r);

Copy the code

Array reduce method added:

arr.reduce(callback,initialValue) // Executes the callback once for each function in the array
The callback function executes a function for each value of the array, containing four arguments
// 1, previousValue (the value returned from the last call to the callback, or the initialValue provided)
// 2, currentValue (array element currently being processed)
// 3, index (current element index in array)
// 4, array (call reduce array)
// initialValue (as the first argument to the first callback call.)
Copy the code

Arguments:

The parameters are matched from left to right. If the arguments are smaller than the parameters, the following arguments are underarticles. length can be used to obtain the length of the function parameters, and the number of arguments can be obtained by using arguments. Use arguments.callee to reference the function itself

About the arguments more: www.jianshu.com/p/d7ed5ade6…

Array.from()// creates a new, shallow-copy Array instance from an array-like or iterable

Regular expression

// regress the base pattern
let expression = /pattern/flags 
Flags include g, global, I case insensitive, and M multi-line
// Use constructors to create regular expressions
let pattern = new RegExp(pattern,flags)

// cvTE interview, phone number regular
let exp1 =  /^1[3456789]\d{9}$/
let exp2 = new RegExp("/^1[3456789]\d{9}$/"."g")
Copy the code

Match rule

About regular expressions more formal arrangement: www.cnblogs.com/xiaoshen666…