A enhanced curry method
JavaScript is a functional language, it supports function composition, we can do curry with JavaScript. Douglas Crockford has defined "curry" method in his book JavaScript: The Good Parts to facilitate the steps to define curried function.
Function.prototype.method = function ( name, func ) {
if ( !this.prototype[name] ) {
this.prototype[name] = func;
}
};
Function.method( 'curry', function () {
var slice = Array.prototype.slice,
args = slice.apply( arguments ),
that = this;
return function () {
return that.apply( null, args.concat( slice.apply( arguments ) ) );
};
} );
//so I can write the following code
test( "test curry", function () {
function cancat_abc( a, b, c ) {
return a + b + c ;
}
var cancatBc = cancatAbc.curry( "a" );
var result = cancatBc( "b", "c" );
equal( result, "abc", "the first parameter is preloaded" );
} );
Nice. But there is problem here, the preloaded arguments have to be the first consecutive arguments. So if I have want to preload the second and third parameter. The curry method does not support that.
Of course, I can do it manually instead of using the curry method, but this is not quite DRY (Don't Repeat Yourself). So I modify the curry method as follow to do the work.
Function._ = {};
Function.method( 'curry', function () {
var slice = Array.prototype.slice,
preloads = slice.apply( arguments ),
_ = Function._,
fn = this;
return function () {
var args = slice.apply( arguments );
for ( var i = 0; i < preloads.length; i++ ) {
if ( preloads[i] == _ ) {
preloads[i] = args.shift();
}
}
return fn.apply( null, preloads.concat( args ) );
};
} );
var _ = Function._;
test( "test curry", function () {
ok( _, "an dummy object has been defined" );
function cancat_abcd( a, b, c, d ) {
return a + b + c + d;
}
var cancatBd = cancatAbc.curry( "a", _, "c", _ );
var result = cancatBd( "b", "d" );
equal( result, "abcd", "curry should work in order" );
} );