R

E

A

C

T

O

xamples 

epeat

ode

pproach

ptimize

est

REACTO: Curry

 

Currying

  • What is currying?
    • ​​Cookin up the sauce, chef curry with them pots :D

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 calcAllFour(var1, var2, var3, var4) {
    return var1 + var2 - var3 * var4;
}

const curriedDoSomething = curry(calcAllFour); // closure memory -> []

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

const secondReturn = firstReturn(2); // closure memory -> [1, 2]

const thirdReturn = secondReturn(3); // closure memory -> [1, 2, 3]

const fourthReturn = thirdReturn(4); // -9 -> (1 + 2 - 3 * 4)

Example cont'd

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

const curriedDoSomething = curry(calcAllFour); // closure memory -> []

const firstReturn = curriedDoSomething(1); // closure memory -> [1]
const secondReturn = firstReturn(2); // closure memory -> [1, 2]
const thirdReturn = secondReturn(3); // closure memory -> [1, 2, 3]
const fourthReturn = thirdReturn(4); // -9 -> (1 + 2 - 3 * 4)

const reuse1 = firstReturn(3, 4, 5); // -16 -> (1 + 3 - 4 * 5)

const reuse2 = secondReturn(7, 8); // -53 -> (1 + 2 - 7 * 8)

Now you must be the Curry

  • Implement the "curry" function 
  • Keep in mind
    • You have to know how many arguments the function that you are currying  takes in
      • The previous example had 4 parameters
    • The function you return from currying must accumulate the number of succeeding arguments
    • The function must determine if arguments accumulated meet the number of parameters the original function require, and return what the original function would return with the accumulated arguments

Possible solution

function curry (originalFunc) {
  let argsMemory = [];

  return function resolver () {
    const args = [].slice.call(arguments);
    argsMemory = argsMemory.concat(args);
    
    if (argsMemory.length >= originalFunc.length) {
      return originalFunc.apply(null, argsMemory) 
    } else {
      return resolver;
    }
  }

}

* Note: interviewee might start with finding a solution for just 4 arguments, and that is a fine place for them to start - during Test or Optimization lead them to a more dynamic answer

Spread/Rest solution

function curry (original) {
  return function curried (...args) {
    if (args.length >= original.length) {
      return original(...args);
    } else {
      return function curriedWithArgs (...nextArgs) {
        return curried(...args, ...nextArgs);
      };
    }
  };
}

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 calcAllFour(a, b, c, d) {
    return a + b - c * d;
}

var curriedDoSomething = curry(calcAllFour)
var steph1 = curriedDoSomething(_, _, _, 4);
var steph2 = steph1(1, 2, 3) // -9 -> (1 + 2 - 3 * 4)

Possible Bonus Solution

function curry( originalFunc ) {
    const __ = this.__ = {};

    const isFilled = list => list.every(item => item !== __);
    const getMemory = function(a) {
        return Array.apply(null, new Array(originalFunc.length))
	          .map(() => a.shift() || __);
    };
	
    const applyToMemory = function(m, a) {
        m.forEach(function(item, index) {
            if (item === __) m[index] = a.shift();
        })
    };

    function resolver(...resolverArgs) {
        const memory = getMemory(resolverArgs);
		
        return function returningFunction (...returningFnArgs) {
	    let next;
	    applyToMemory(memory, returningFnArgs);
            
            if (isFilled(memory)) next = originalFunc;    
            else next = resolver;   

            return next.apply(null, memory); 
	};
    }

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

const __ = curry.__;
const curried = curry(calcAllFour);
const lastOne = curried(__, __, __, 4);
lastOne(1,2,3); // -9 -> (1 + 2 - 3 * 4)

Reacto: curry

By Kate Humphrey

Reacto: curry

Technical interview practice problem

  • 891