What do you think of Currization

The idea of currization is to convert a multivariate function into a unit function that is called sequentially. This use of Curry can be understood as parameter reuse. In essence, it is to reduce generality and improve applicability.

F (a, b, c) and f (a) (b) (c)var add = function(x) {
  return function(y) {
    return x + y;
  }; 
};
const increment = add(1);

increment(10); / / 11
Copy the code
var { curry } = require('lodash')

var abc = function(a, b, c) {
  return [a, b, c];
};
 
var curried = curry(abc);
 
console.log(curried(1) (2) (3));
// => [1, 2, 3]
 
var person = [{name: 'kevin'.age: 12 }, {name: 'daisy'.age: 13}]

var prop = curry(function (key, obj) {
  return obj[key]
});

// Common mode
var name = person.map(function (item) {
    return item.name;
})

// Currization
var name = person.map(prop('name'))
console.log(name) // [ 'kevin', 'daisy' ]

var age = person.map(prop('age'))
console.log(age) // [12, 13]
Copy the code






Above code, we will return the object attributes of the part through functional programming.

var prop = curry(function (key, obj) {
  return obj[key]
});
Copy the code

The curry function will pass in two arguments to function. Becomes two functions that take one argument.

function(key, obj) // Convert to two functions according to the Currie transformation, and the first argument returns a function with the second argument of the original function.props(key) = >function(obj)
Copy the code


Closures are used to store arguments, and when there are enough arguments to execute the function, the function is executed

Handwriting currization

The initial release


var abc = function(a, b, c) {
  return [a, b, c];
};

function customerCurry(fn) {
  const fnArgsCount = fn.length;  	// The number of parameters of the fn function
  let curryArgs = [];			// The number of real numbers that have been passed into the Currization function
  
  function wrapperFunction () {
    curryArgs = curryArgs.concat([...arguments])
      
    if (curryArgs.length < fnArgsCount) {
      return wrapperFunction;
     }
      
     return fn.apply(this, curryArgs)
   }
  
   return wrapperFunction;
}

var incre = customerCurry(abc)
incre(1) (2) (3)  // Return normal [1, 2, 3]

incre() 				// Return [1, 2, 3]
Copy the code

The above code returns normally, but there is still a problem. Incre cannot be executed multiple times. Here the parameters are uniformly recorded because of the way they are written. The customerCurry parameter is the outermost must be wrapped in maintenance. So after incre(1), (2), (3) is executed. The number of internal parameters has reached three. Procedure


The second version


var abc = function(a, b, c) {
  return [a, b, c];
};

function customerCurry(fn) {
  	const fnArgsCount = fn.length;  	// The number of parameters of the fn function
  	let curryArgs = [];								// The number of real numbers that have been passed into the Currization function
  
		if (fnArgsCount <= 1) {
    	throw new Error('Function takes at least two arguments');
    }
  
  	function wrapperFunction () {
    	curryArgs = [...arguments];
      
      if (curryArgs.length < fnArgsCount) {
      	return eval(`wrapperFunction.bind(this, ${curryArgs.reduce(function(x, y) {return x + ', ' + JSON.stringify(y); })}) `);
      }
      
      return fn.apply(this, curryArgs)
    }
  
  	return wrapperFunction;
}

var incre = customerCurry(abc)
incre(1) (2) (3)  // Return normal [1, 2, 3]
Copy the code

Of course, this is flawed, because it doesn’t handle the passing of parameters very well, using json.


The third version


var abc = function(a, b, c) {
  return [a, b, c];
};

function customerCurry(fn) {
  	const fnArgsCount = fn.length;  	// The number of parameters of the fn function
  	const curryWrapperArgs = [...arguments].slice(1);
  
  	function wrapperFunction () {
    	let curryArgs = [fn, ...curryWrapperArgs, ...arguments];
      
      if (curryArgs.length < fnArgsCount + 1) {
      	return customerCurry.apply(this, curryArgs);
      }
      
      return fn.apply(this, curryArgs.slice(1))}return wrapperFunction;
}

var incre = customerCurry(abc)
incre(1) (2) (3)  // Return normal [1, 2, 3]
Copy the code




The fourth edition

That’s fine to write, but now that you’ve learned the cremation, the idea of functional programming let’s write it. Example source: github.com/mqyqingfeng…

/ / the second edition
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); }}; }Copy the code


Order of execution:





Change direction:









Now let’s think about it in terms of functional programming.












Fifth edition: high appearance level writing method

var curry = fn= >
    judge = (. args) = >args.length === fn.length ? fn(... args) :(arg) = >judge(... args, arg)Copy the code


With reference to

  • Github.com/mqyqingfeng…
  • Juejin. Cn/post / 684490…