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.
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)
Well, I can't tell you what, exactly autoCurry
is doing... ...but what I can tell you is this:
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();
You can chain statements together, happily in JS.var myObj = { run : function () { } }, result = myObj.run();
is the same asvar result = { run : function () { } }.run();
, as long as you don't care about myObj
after.
So:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With