R

E

A

C

T

O

xamples 

epeat

ode

pproach

ptimize

est

REACTO: Currying

 

Currying

a, b

curry

a

b

a b

Formal Definition:

"Currying is the process by which a function of N arguments is implemented as N single-argument functions such that first of them takes in the first argument and returns a function which takes in the 2nd argument and so on, until the Nth single-argument function finally returns the value of the multi-argument function being implemented."

Example

function addAllFour(var1, var2, var3, var4) {
	return var1 + var2 - var3 * var4;
}

var curriedDoSomething = curry(addAllFour) // closure memory -> []

var firstReturn = curriedDoSomething(1) // closure memory -> [1]

var secondReturn = curriedDoSomething(2) // closure memory -> [1 , 2]

var thirdReturn = curriedDoSomething(3) // closure memory -> [1, 2, 3]

var fourthReturn = curriedDoSomething(4) // -9 (1 + 2 - 3 *4)

Example 2

function doMath(a, b, c, d) {
    return a + b - c * d;
}

var curried = curry(doMath);

var makeOne = curried(1);
var makeTwo = makeOne(2);

var returned1 = makeOne(3, 4, 5); // -16 (1 + 3 - 4 * 5)
var returned2 = makeTwo(4, 5) // -17 (1 + 2 - 4 * 5)

Approach

  • Function takes a function, returns a new "curried" function
  • The "curry creating" function will determine the total number of N arguments required
  • The "curry creating" function will keep track of the arguments as they are provided
  • Once the total number of arguments provided equals the required N number of arguments, execute the original function with all the arguments
  • Learn more about currying: trasb.org/currying

Possible Solution

function curry(originalFunc) {
    var originalLength = originalFunc.length;

    function resolver() {
	var memory = Array.prototype.slice.call(arguments);
		
	return function() {
	    var args = Array.prototype.slice.call(arguments);
	    var copy = memory.concat(args);

	    if (copy.length >= originalLength){
                return originalFunc.apply(null, copy);
            }
	    else return resolver.apply(null, copy);
	};
    };

    return resolver();
}

ES6 Solution with IIFE

function curry(originalFunc) {
    var originalLength = originalFunc.length;

    return (function resolver() {
	var memory = Array.from(arguments);
		
    	return function() {
    	    var args = Array.from(arguments);
    	    var copy = memory.concat(args);
    
    	    if (copy.length >= originalLength){
                    return originalFunc(...copy);
            }
    	    else return resolver(...copy);
    	};
    })();

}

Bonus

  • The thing about the example and solution previously is that you have no control with orders. The arguments will always be passed left to right
  • Edit the curry function and the example to where you control the order of the arguments
function doMath(a, b, c, d) {
    return a + b - c * d;
}

var steph1 = curried(/* Do Something */ 1);
var steph2 = steph1(1, 2, 3) // 0 (1 + 2 - 3 * 1)

Possible Solution

Made with Slides.com