0

I'm reading about Function currying in Javascript. I got the concept and the examples were easy to understand.

But then, the author of the article says that currying a function too much can be messy as for the multiple nested returns, and shows a function to curry another function passed as argument.

var curryIt = function(uncurried) {

var parameters = Array.prototype.slice.call(arguments, 1);

return function() {
   return uncurried.apply(this, parameters.concat(
     Array.prototype.slice.call(arguments, 0)
    ));
  };
};

Then applies it this way

var greeter = function(greeting, separator, emphasis, name) {
  console.log(greeting + separator + name + emphasis);
};

var greetHello = curryIt(greeter, "Hello", ", ", ".");

greetHello("Heidi"); //"Hello, Heidi."
greetHello("Eddie"); //"Hello, Eddie."

curryIt is the function that curries another function. How exactly is doing that?

Though there is no unfamiliar code to me I seem not to get it.

user1869935
  • 717
  • 2
  • 10
  • 23
  • 3
    As so often, it *[does not do currying](https://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application)*. It does partial application. – Bergi Oct 11 '16 at 19:56
  • If you are familiar with the single things, what exactly don't you get? – Bergi Oct 11 '16 at 19:58
  • This seems to be a terrible way of explaining currying. – Redu Oct 11 '16 at 20:04

1 Answers1

1

Technically, this is partial application but the two ideas are very closely related.

Anyway, let's break down your code:

var curryIt = function(uncurried) {
  // Get all of the parameters except for `uncurried`
  var parameters = Array.prototype.slice.call(arguments, 1);

  // Return a new function such that...
  return function() {
    // The function you passed in, `uncurried` is called
    return uncurried

      // apply - Use an array for arguments instead of positional arguments
      // i.e, f(a, b, c) === f.apply(this, [a, b, c])
      .apply(

        // Set the value of `this` in `uncurried`
        this, 

        // Create a copy of the original `parameters` array and add...  
        parameters.concat(

          // ...the arguments that were passed to the anonymous function
          Array.prototype.slice.call(arguments, 0)
      ));
  };
};

By looking at how parameters changes, you can get a feeling for how it works.

var curryIt = function(uncurried) {
  var parameters = Array.prototype.slice.call(arguments, 1);
  console.log('curryIt: ' + parameters.join(' '));

  return function() {
    var newParams = Array.prototype.slice.call(arguments, 0);
    console.log('anonymous: ' + newParams.join(' '));
    
    // Prepare the arguments here so we can see them
    var args = parameters.concat(newParams);
    console.log('Full call: ' + args.join(' '));
    return uncurried.apply(this, args);
  };
};

function f(a, b, c, d) {
  console.log('Finished: ' + [a, b, c, d].join(' '));
  console.log(' ');
}

var g = curryIt(f, 1, 2);
g(3, 4);

g(10, 20);
Community
  • 1
  • 1
Mike Cluck
  • 31,869
  • 13
  • 80
  • 91