Underscore supports partials with _.bind()
, the only downside is that you have to always pass this
. So I wanted to see how hard it would be to create my own version of partial.
This is of course a silly exercise, ECMAScript 5th Edition provides a fun.bind()
method that _.bind()
will use that if you have at least IE 9. I just find always passing the this
parameter ugly and from my understanding of functional programming you shouldn't be using this
in a partial anyways.
##Here is my first attempt.
var partial = function(){ var args = Array.prototype.slice.call(arguments), fn = args.shift(); return function(){ return fn.apply(fn, args.concat(Array.prototype.slice.call(arguments) )); }}
##You can call it like:
function aBC(a, b, c) { return a + b + c; }
var bC = partial(aBC, 20);
bC(30, 40);
// or using _.bind
function aBC(a, b, c) { return a + b + c; }
var bC = _.bind(aBC, undefined, 20);
bC(30, 40);
// or using fun.bind
function aBC(a, b, c) { return a + b + c; }
var bC = aBC.bind(undefined, 20);
bC(30, 40);
apply
takes an argument for this
, much like _.bind()
does. I just set it to the function being used in the partial. I'm not sure if that is correct or not.
It seems to work pretty well, but I'm sure a little golfing can make it a lot better.
##My first golf attempt is:
var partial = function(){ var slice=Array.prototype.slice, args = slice.call(arguments), fn = args.shift(); return function(){ return fn.apply(fn, args.concat(slice.call(arguments))); }}
Which only saves 4 characters. Not a very good attempt.
##Using Bind
Since when using a partial it doesn't matter what this
is (hence passing undefined
) I tried to figure out what would be the shortest thing to pass as this
. So far the best I've come up with is []
it's only two characters, but I don't like that you have to press shift to get those characters.
function aBC(a, b, c) { return a + b + c; }
var bC = aBC.bind([], 20);
bC(30, 40)
What I would really like is to use _.bind (or the native bind) to create a partial method that doesn't take this
.
// with underscore bind
var partial=function(){var args=Array.prototype.slice.call(arguments),fn=args.shift();return _.bind.apply([],[fn,[]].concat(args));}
// with native bind
var partial=function(){var args=Array.prototype.slice.call(arguments),fn=args.shift();return fn.bind([],args);};
#Conclusion I'm happy with the way these turned out. I wanted the solution to be tweetable and both versions are less than 140 characters. The native version is a little bit smaller and doesn't require underscore, but it won't work in IE8.
All of this is just so you can write partial(test, 13);
instead of test.bind(undefined, 13);
I think it's cleaner, but requires adding this code to your library somewhere.