Skip to content

Instantly share code, notes, and snippets.

@ripter
Created May 23, 2012 06:25
Show Gist options
  • Save ripter/2773531 to your computer and use it in GitHub Desktop.
Save ripter/2773531 to your computer and use it in GitHub Desktop.
Partial method

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment