sequence
The “typical” methods and processes of imperative programming are deeply rooted in their environment, through states, dependencies, and effective actions; Pure functions, by contrast, are context-independent and can be run anywhere we want
The problem with object-oriented languages is that they always carry around those implicit environments. All you need is a banana and you get a gorilla with a banana… And the whole jungle.
A function of first-class citizenship
Can be passed as variables, returned, or nested within functions, can be used as arguments, and uses expressions that always return values instead of statements.
Pure functions should be natural and have no side effects
A pure function is one in which the same input always returns the same output without any observable side effects.Copy the code
A side effect is an interaction between the inside and outside of a function that produces a result other than the operation. For example, a function that uses and modifies external variables during a function call is a function with side effects.
In summary, side effects include:
- Changed any external variables or object properties (for example, global variables, or a variable in the parent function’s scope chain)
- Write the log
- On-screen output
- Write files
- Sending network Request
- Trigger any external processes
- Call another function that has side effects
Slice and splice, for example, do the same thing — notice that they work in very different ways, but still do the same thing. Slice conforms to the definition of a pure function because it is guaranteed to return the same output for the same input. Splice, on the other hand, chews up the array that calls it and spits it out. This has the observable side effect of permanently changing the array.
var xs = [1.2.3.4.5];
/ / pure
xs.slice(0.3);
/ / = > [1, 2, 3]
xs.slice(0.3);
/ / = > [1, 2, 3]
xs.slice(0.3);
/ / = > [1, 2, 3]
/ / not pure
xs.splice(0.3);
/ / = > [1, 2, 3]
xs.splice(0.3);
/ / = > [4, 5)
xs.splice(0.3);
/ / = > []
Copy the code
In functional programming, we hate stupid functions that change data. We are looking for a reliable function that returns the same result every time, not a function like Splice that messes up the data every time it is called, which is not what we want.
Let’s look at another example.
/ / not pure
var minimum = 21;
var checkAge = function(age) {
return age >= minimum;
};
/ / pure
var checkAge = function(age) {
var minimum = 21;
return age >= minimum;
};
Copy the code
Curry
Transform a function that takes multiple arguments into a function that takes a single argument (the first argument of the original function), and return a new function that takes the remaining arguments and returns the result
function sub_curry(fn) {
var args = [].slice.call(arguments.1);
return function() {
return fn.apply(this, args.concat([].slice.call(arguments)));
};
}
function curry(fn, length) {
length = length || fn.length;
var slice = Array.prototype.slice;
return function() {
if (arguments.length < length) {
var combined = [fn].concat(slice.call(arguments));
return curry(sub_curry.apply(this, combined), length - arguments.length);
} else {
return fn.apply(this.arguments); }}; }// Let's verify this function:
var fn = curry(function(a, b, c) {
return [a, b, c];
});
fn("a"."b"."c") // ["a", "b", "c"]
fn("a"."b") ("c") // ["a", "b", "c"]
fn("a") ("b") ("c") // ["a", "b", "c"]
fn("a") ("b"."c") // ["a", "b", "c"]
Copy the code
So let’s take fn(“a”)(“b”)(“c”) step by step.
curry
The function is passed in and assigned tofn
.curry
In the functionlength
for3
Returns a function.- when
fn("a")("b")("c")
, executes the function returned in the previous step, i.ecurry() { return function() {.... }}
, here for convenience, willcurry
The function returned is calledfun
fn("a")
When,fun
thearguments.length
Is 1, so the block of code that executes the if statement.- will
function(a, b, c) {return [a, b, c]; }
Function as an array parameter value andfun
thearguments
Link ([fn].concat(slice.call(arguments)). - The callback
curry
.curry
The first parameter of issub_curry
The function returns a value that carriesfunction(a, b, c){... }
Function anda
Value. How many different parameters does the second parameter function? - Repeat steps after Step 2 (but at this point
length
for2
)
Of course, if you still don’t understand, you can use the following implementation to achieve the same effect:
function curry(fn, args) {
let length = fn.length;
args = args || [];
return function() {
let _args = args.slice(0)
for (let i = 0; i < arguments.length; i++) {
_args.push(arguments[i])
}
if (_args.length < length) {
return curry.call(this, fn, _args)
} else {
return fn.apply(this, _args)
}
}
}
var fn = curry(function(a, b, c) {
console.log([a, b, c])
});
fn("a"."b"."c") // ["a", "b", "c"]
fn("a"."b") ("c") // ["a", "b", "c"]
fn("a") ("b") ("c") // ["a", "b", "c"]
fn("a") ("b"."c") // ["a", "b", "c"]
Copy the code
And maybe you think this is a better way to understand it, but it does the same thing, so why don’t you just do it this way?
Because I want to introduce various implementation methods, we can not just because it is difficult to understand not to introduce to you
Code composition (compose)
Function to raise
This is the composition (hereafter referred to as composition) :
var compose = function(f,g) {
return function(x) {
return f(g(x));
};
};
Copy the code
F and g are functions, and x is the value “piped” between them.
Combinations look like feeding functions. You are the breeder. Choose two functions that have special features and that you like and combine them to produce a brand new function. Combinations can be used as follows:
var toUpperCase = function(x) { return x.toUpperCase(); };
var exclaim = function(x) { return x + '! '; };
var shout = compose(exclaim, toUpperCase);
shout("send in the clowns");
//=> "SEND IN THE CLOWNS!"
Copy the code
It makes perfect sense to combine two functions and then return a new function: combining two elements of a type (in this case, a function) should generate a new element of that type. You can’t put two Legos together and get a Lincoln. So it makes sense, and we’ll explore some of the underlying theories of this in due course.
In the definition of compose, g will execute before f, so a right-to-left data flow is created. This is much more readable than nesting a bunch of function calls, and if not combined, the shout function would look like this:
var shout = function(x){
return exclaim(toUpperCase(x));
};
Copy the code
Let’s look at some other examples
var compose = function (f, g) {
return function (x) {
return f(g(x));
};
}
var add = function (x) {
let y = x + 1
console.log('add', y)
return y
}
var reduce = function (x) {
let y = x - 1
console.log('reduce', y)
return y
}
var multiplication = function (x) {
let y = x * 2
console.log('multiplication', y)
return y
}
// var fruit = compose(reduce, compose(add, multiplication)); // 200
var fruit = compose(compose(reduce, add), multiplication); / / 200
fruit(100)
Copy the code
Now it’s time to look at one feature that all combinations have.
// Associativity
var associative = compose(f, compose(g, h)) == compose(compose(f, g), h);
// true
Copy the code
This property is associative, and associative means that it doesn’t matter whether you put g and H in a group or f and G in a group.
Share not easy forehead, like words must not forget to point 💖!!
Pay attention to not point 💖 only is play hooligan, collect only also not point 💖 also is play hooligan.
reference
Functional programming is north
JavaScript- Functional programming