Function Programming

This article is a reading note from my book on JavaScript functional programming. Use the underscore framework to introduce several concepts of functional programming.

Higher-order functions

1. Take functions as arguments;Copy the code
<! The councilman warned me repeatedly -->function repeatedly(times,value){
        return _.map(_.range(times), () = > {returnvalue }) } <! Warning: warning: repeatedlyfunction repeatedly(times,fun){
        return _.map(_.range(times),fun)
    }

    repeatedly(3,function() {return Math.floor(Math.random()*10+1)
    })
Copy the code

Warning is a classic idea of functional programming: change values into functions.

2. A function that returns other functions.Copy the code

React and Redux use a lot of functions that return other functions. Includes higher-order components, applyMiddleware functions. The Thunk function is also a function that returns other functions.

    var Thunk = function(fn){
        return function(){
            var args = Array.prototype.slice.call(arguments);
            return function(callback){
                args.push(callback);
                return fn.apply.(this,args);
            }
        }
    }

    var readFileThunk = Thunk(fs.readFile);

    readFileThunk(fileA)(callback);
Copy the code

Functions build functions from functions

  1. Functional essence (dispatch function);
    function existy(x) {
        returnx ! = null; }function doWhen(cond, action) {
        if (tructhy(cond))
            return action();
        else
            return undefined;
    }
    function invoker(NAME, METHOD) {
        return function (target) {
            if(! existy(target)) { alert('Must provide a target');
            }
            var targetMethod = target[NAME];
            var args = _.rest(arguments);
            return doWhen(existy(targetMethod) && METHOD === targetMethod, function () {
                returntargetMethod.apply(target, args); }); }}function dispatch() {
        var funs = _.toArray(arguments);
        var size = funs.length;

        return function (target) {
            var ret = undefined;
            var args = _.rest(arguments);
            for (var funIndex = 0; funIndex < size; funIndex++) {
                var fun = funs[funIndex];
                ret = fun.apply(fun,construct(target,args))
                if(existy(ret)) return ret;
            }
            
            if(existy(ret)) return ret;
        }
    }

    var str = dispatch(invoker('toString',Array.prototype.toString),invoker('toString',String.prototype.toString));
    console.log(str('a'));
    console.log(str(_.range(10)));
Copy the code

Dispatch combines multiple invokers together to form polymorphic functions, or to produce parameters with different behaviors based on different parameters. 2. Corrification. For each logical argument, the Cremation function returns the configured function gradually until all arguments are used up.

function curry(fun){
    return function(firstArg){
        retun function(secondArg){
            returnfun(firstArg,secondArg); }}}Copy the code
  1. Partial application. The Coriation function gradually returns the function that consumes the arguments until all the arguments are exhausted, whereas the partially applied function is a “partially executed” argument that waits to receive the remaining arguments immediately.
function partApply(f, x) {
  return function(y) {
    returnf(x, y); }}Copy the code
  1. By combining end-to-end splicing functions. An ideal functional program is a piece of data that flows to one end of the pipeline and outputs a whole new piece of data from the other end. For example:! _isString(name);
  • _isString receives an object and returns a Boolean value.
  • ! Receives a Boolean and returns a Boolean.

The compose function is executed from right to left. That is, the result of the rightmost function is fed into the function to its left, one by one.

function not(x){
    return! x; } var isntString = _.compose(not,_isString);Copy the code

Purity, immutability and change policy.

  1. pure function
  • The result can only be calculated from the values of its arguments.
  • Do not rely on data that can be changed by external operations.
  • You cannot change the external state. JavaScript causes impure functions or methods such as date.now (),console.log(),this and global variables.
  1. Immutability of data. (immutablejs);
function touchAndLog(touchFn) {
  let data = { key: 'value'}; touchFn(data); console.log(data.key); // Guess what will be printed? }Copy the code

Without looking at touchFn’s code, it’s impossible to know what will be printed because you’re not sure what it does to data. But if data is Immutable, you can be pretty sure that you are printing value.

  1. Change the policy. Take any object and change it. A better strategy is to put the object in the container and change the container.

Stream-based programming.

  1. Inert chain.
function LazyChain(obj){
    this._calls = [];
    this._target = obj; 
}

LazyChain.prototype.invoke = function(methodName){
    var args = _.rest(arguments);
    this._calls.push(function(target){
        var meth = target[methodName];
        return meth.apply(target,args);
    })

    return this;
}


LazyChain.prototype.force = ()=>{
    return _.reduce(this._calls,function(target,thunk){
        returnthunk(target); }}, enclosing _target) new LazyChain ([1, 2, 3]). Invoke ('sort').force();

Copy the code