Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when you declare .autoCurry() on a function declaration in JavaScript?

Tags:

javascript

I came across this syntax in "Hey Underscore, You're Doing it Wrong" JavaScript talk (4:15). I would like to know what it means.

var add = function(x,y){
    return x + y;
}.autoCurry();//What is happening in this line.
like image 418
Taimoor Avatar asked Jan 14 '14 00:01

Taimoor


2 Answers

First let's looks at what curry and autocurry actually do. I've annotated the source of these two functions (originally found in the wu.js library):

  ////
  // Type:
  //
  //   ((a,b, ... c) -> d) -> a -> b -> ... -> c -> d
  //
  // Example:
  //
  //   function add(a, b) { return a + b; }
  //   add2 = curry(add, 2)
  //   add2(3)
  //   // 5
  function curry(fn /* variadic number of args */) {
    var args = Array.prototype.slice.call(arguments, 1);
    function f() { return fn.apply(this, args.concat(toArray(arguments))); }
    return f;
  }

  ////
  // Example:
  //
  //   function add(a, b) { return a + b; }
  //   autoCurry(add);
  //
  //   add(2)(3)                     
  //   // 5
  //
  //   add(2, 3) 
  //   // 5 
  function autoCurry(fn, numArgs) {
    numArgs = numArgs || fn.length;
    function f() {
      if (arguments.length < numArgs)
      {
        return numArgs - arguments.length > 0 ?
        autoCurry(curry.apply(this, [fn].concat(toArray(arguments))),
        numArgs - arguments.length) :
        curry.apply(this, [fn].concat(toArray(arguments)));
      }
      else
      {
        return fn.apply(this, arguments);
      }
    }
    f.toString = function() { return fn.toString(); };
    f.curried = true;
    return f;
  }

In other words,

autoCurry(add)

Takes a function that takes two arguments and returns a number, and returns a function A that takes a single argument and returns a function B. Where B is a function that takes a single argument and returns a number:

add(1) -> returns a function add1(), which itself takes a single argument. 

Next, the speaker in that talk does the following:

  Function.prototype.autoCurry = function(n) { return autoCurry(this, n); }

This simply applies the autoCurry method to any given function (self) so that

var add = function(x,y){
    return x + y;
}.autoCurry();

Has the same effect as:

var add = function(x,y) { return x + y; };
add = autoCurry(add)
like image 137
o_o_o-- Avatar answered Oct 30 '22 16:10

o_o_o--


Well, I can't tell you what, exactly autoCurry is doing... ...but what I can tell you is this:

  1. They've modified the Function constructor's prototype Function.prototype.autoCurry = function () { };
    Every new function you make on that page will now have access to this method as one of its properties.
    var myFunc = function () { return true; }; myFunc.autoCurry();

  2. You can chain statements together, happily in JS.
    var myObj = { run : function () { } }, result = myObj.run(); is the same as
    var result = { run : function () { } }.run();, as long as you don't care about myObj after.

So:

  1. You are creating a function, and as soon as it's created, you're running a method on it, and the return statement of that method (the last thing in the chain) is being saved to the variable.

Now, currying is a form of taking a function and wrapping it in other functions, which allows you to call it with only a portion of the arguments needed.

function add_two_numbers = function (x, y) { return x + y; }

Currying would allow you to do this:

var save_x_for_later = curry(add_two_numbers),
    save_y_and_add   = save_x_for_later(3),
    result = save_y_and_add(5);

result; // 8

As for your new title, the answer is the following: You will get an error thrown in your face: .autoCurry() is not a part of the language. It was written, by hand, and put on the Function.prototype as Function.prototype.autoCurry = function () { }

I could go into an implementation of currying, but there's a lot of stuff to wrap your head around, if you haven't done much functional programming, or if "lambda" is a head-scratching term.

like image 35
Norguard Avatar answered Oct 30 '22 17:10

Norguard