What is functional programming?
- Describes the mapping between data
- There are inputs and outputs, and the same inputs give the same outputs (pure functions)
Functions of functional programming:
- You can drop this
- Better Use of Tree Sharking for filtering garbage code in packaging
- Functional programming can be reused, or new functions can be combined to make them more powerful
Functions related concepts:
First class citizen: [Function as first citizen is a necessary condition for functional programming]
- Can be used as a parameter
- Can be used as a return value
- You can also assign to variables
Higher-order functions:
- Accept functions as arguments or output functions as return values
Closure:
- Closures are functions that can read variables inside other functions.
- In javascript, for example, local variables can only be read by child functions inside a function, so closures can be understood as “functions defined inside a function.”
- In essence, closures are Bridges that connect the inside and outside of a function
Pure functions: [Advantages: uncomplicated, easier to debug, easy to combine, easy to parallelize]
- You should always return the same value
- Self-contained
- It should not alter the state of the program or cause side effects.
Corrification: [Can transform any function of multiple variables into a function of one variable (a function with multiple parameters is a function of multiple variables)]
- Currization is a transformation that converts f(a,b,c) into something that can be called as f(a)(b)(c). JavaScript implementations typically leave the function callable and return partial functions if the number of arguments is insufficient
- That is, when a function has more than one argument, it is called by passing it a set of arguments (which will never change), and it returns a function that processes the rest of the arguments and returns the result
Function composition
- The process of combining two or more functions to produce a new function. Putting functions together is like aligning a series of pipes to allow our data to flow through
- Function combinations are executed from right to left and from inside out by default
Functor related concepts:
- A functor is a container containing values and their metamorphosis relations (metamorphosis refers to functions)
- Representative functor is a concept in category theory. There is no way to avoid side effects, but we can control side effects in a controllable range by means of functors. Meanwhile, we can also handle exceptions and asynchracy by means of functors
Functor Functor
- Functor is a container type that implements a map function and follows certain rules.
- Only one property object (which can be any type of value)
- Implements a map function that takes a function as an argument and returns a new functor object
Constructor () {this._value = value} // Receive a function, Map (fn) {return new Functor(fn(this._value))}} let num1 = new Functor(3).map(val => val + 2) Console. log(num1) // Output: Functor {_value: 5} let num2 = new Functor(3).map(val => val + 2).map(val => val * 2) console.log(num2) Let num3 = new Functor('webpack').map(val => '${val}-cli ').map(val => val.length) console.log(num3) // Functor {_value: 11}Copy the code
Pointed functor
- A functor that implements the of static method is called a conservative functor. Instead of using new to create objects, the deeper implication is that the of method is used to put values in context.
Class conservative {// static method, Static of (value) {return new Pointed(value)} constructor (value) {this._value = value} map (fn) {return new point (value)} constructor (value) {this._value = value} map (fn) { return Pointed.of(fn(this._value)) } } let pointed = Pointed.of(3).map(val => val + 1).map(val => val * 2) Console. log(50%) // Output: 50% {_value: 8}Copy the code
MayBe functor
- The Maybe functor checks to see if its value is null before calling the function passed in, so it can handle null values without error.
- The Maybe functor is commonly used in functions that may not return a result successfully; You can avoid the imperative if… Else statements, Maybe(null) can be used to indicate failure, but it does not tell us much useful information, such as: What is the cause of the failure? What caused the failure? The Either functor can help us solve such problems.
class Maybe { static of (value) { return new Maybe(value) } constructor (value) { this._value = value } map (fn) { // Return this._value? Maybe.of(fn(this._value)) : Maybe.of(null)}} let toUpper = maybe.of (null).map(x => x.toupperCase ()) console.log(toUpper) Function getFirst(arr) {return may.of (arr[0])} let firstElement = getFirst([]).map(x => X + 3) console.log(firstElement) : Maybe {_value: null}Copy the code
Either functor
- In normal object-oriented programming, we usually use the conditional operation statement if… The else… Make judgments about anomalies and so on. In functional programming, exceptions make functions impure, and we use Either functors for exception handling
- In functional programming, use Either functors instead of conditional operators (if… The else); Another use is instead of try… catch
- Either functors typically have two values inside them: Left and Right, which indicate errors, and vice versa
Class Left {static of (value) {return new Left(value)} constructor (value) {this._value = value this map (fn) { return this } } class Right { static of (value) { return new Right(value) } constructor (value) { This._value = value} map(fn) {return right.of (this._value)}} // Left ignore map its function let Left = left.of ('rain').map(STR) => 'b${STR}') console.log(left) Of ('rain').map(STR => 'b${STR} ') console.log(right) {_value: ParseJson (jsonStr) {try {return right.of (json.parse (jsonStr))} catch (e) {return Left. Of (e.message)}} let error = parseJson('{name: zs}') console.log(error) 'Unexpected token n in JSON at position 1' } let success = parseJson('{"name": "Zs "}') console.log(success) : Right {_value: {name: 'zs'}}Copy the code
Monad functor
- A functor is a container that can contain any value. Therefore, it is perfectly legal to include another functor in a functor. However, this will result in multiple layers of nested functors.
- Always return a single functor to avoid nesting. It has a flatMap method that, if a nested functor is generated, fetches the values inside the nested functor, ensuring that a single-layer container is returned to avoid nesting.
- The application of Monad functors is to implement IO (input, output) operations
class Monad { static of (value) { return new Monad(value) } constructor (value) { this._value = value } map (fn) { return Monad.of(fn(this._value)) } join() { return this._value } flatMap (fn) { return this.map(fn).join() } } // map Let nested = monad.of (3).map(val => monad.of (val + 2)) // output: Monad {_value: Monad {_value: 5}} console.log(nested) // If map returns functors, FlatMap (val => monad.of (val + 2)) // Output: monad {_value: 5} console.log(monad)Copy the code
IO functor
- IO functors are used to solve the problem that many functions become impure (side effects) due to their dependence on the external environment
- IO functors differ from previous functors in that the _value inside is always a function. Treat functions as values.
- IO functors can store impaled data in _value for processing, delay the execution of the impaled operation, and consider that IO contains the return value of the wrapped operation.
- Leave impure operations to the caller
const { compose } = require('ramda') const fs = require('fs') class IO { static of (value) { return new IO(function () { return value }) } constructor (fn) { this._value = fn } map (fn) { return new IO(compose(fn, This._value))} join () {// Notice the difference between this line and the example above, because _value is a function, Return this._value()} flatMap (fn) {return this.map(fn).join()}} let readFile = function (filename) {return new IO(function () { return fs.readFileSync(filename, 'utf-8')})} let print = function (x) {return new IO(function () {return x})} Let file = readFile('package.json').flatmap (print).join() console.log(file) // will output package.json Json).flatmap (readFile).flatmap (print).join() console.log(content) // Output The contents of the package.json fileCopy the code