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.

  1. curryThe function is passed in and assigned tofn.
  2. curryIn the functionlengthfor3Returns a function.
  3. whenfn("a")("b")("c") , executes the function returned in the previous step, i.ecurry() { return function() {.... }}, here for convenience, willcurryThe function returned is calledfun
  4. fn("a")When,funthearguments.lengthIs 1, so the block of code that executes the if statement.
  5. willfunction(a, b, c) {return [a, b, c]; }Function as an array parameter value andfuntheargumentsLink ([fn].concat(slice.call(arguments)).
  6. The callbackcurry.curryThe first parameter of issub_curryThe function returns a value that carriesfunction(a, b, c){... }Function andaValue. How many different parameters does the second parameter function?
  7. Repeat steps after Step 2 (but at this pointlengthfor2)

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