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" ); } );