Nerdworks logo "The nerd shall inherit the earth."

Nerdworks Blogorama

Nerdspeak

Partial function application in JavaScript
Technobabble
11/7/2011 9:32:22 AM

Partial function application is a functional programming technique that allows you to transform functions that take N parameters into functions that take a subset of N parameters. For example, say you have this fairly useless function:

function add(a, b) {
    return a + b;
}

Let’s say that for some reason we need a version of "add" that will always have the value 5 for the parameter "a". One way we might do it is like so:

function add5(b) {
    return add(5, b);
}

No black magic there. I was wondering if there might be some way that we can automate the process of generating functions with part of their arguments pre-bound. Here’s what I came up with:

function partialBind(f, context) {
    // arguments length MUST be greater than 2
    if(arguments.length <= 2) {
        // coz. what're you "partial binding" otherwise?!
        return null;
    }

    // convert args to array excluding param "f" and "context"
    var arrayProto = Array.prototype;
    var params = arrayProto.slice.call(arguments, 2, arguments.length);
    return function () {
        // append params passed to this function to "params"
        var args = params.slice(0, params.length);
        if (arguments.length > 0) {
            arrayProto.forEach.call(arguments, function (p) {
                args.push(p);
            });
        }

        // call the original function
        return f.apply(context, args);
    }
}

This function allows me to transform pretty much any function that takes at least 1 argument into a new function that takes a subset of the arguments. Transforming our "add" function into a single parameter version with "a" bound to 5 for instance, would now look like this:

var add5 = partialBind(add, null, 5);
var val = add5(10);
assert(val === 15);

Interestingly, "partialBind" allows us to compose argument binding to multiple levels. If we wanted to take our "add5" function and create another version that binds the second parameter to, say 20, then we can do this:

var add5_20 = partialBind(add5, null, 20);
var val = add5_20();
assert(val === 25);

Note that we are doing a partial bind of a function that is already a partial bind of another function. Turns out we can take this to as many levels as we want. The example given above is of course somewhat concocted because we could have achieved the same result with a single partial bind instead of doing it in two levels:

var add5_20 = partialBind(add, null, 5, 20);
var val = add5_20();
assert(val === 25);

All of this works because JavaScript supports closures. Pretty nifty don’t you think?

 
Hitesh 12/12/2011 9:11:13 PM
Nice artcile with
 
Ranju V 12/12/2011 9:12:53 PM
Thanks Hitesh!
 

Please fill this form and click on the "Submit" button to post a comment. All fields except the comment box are optional. You don't have to give me your name and email, but if you do then that might allow me to follow up with you on your comment. Also, I won't publish your email address here or anywhere else.

 
Your Name :
Your Email :
Your Comment :
   

What in your opinion do you get when you multiply the number 5 by the number 2?

Your answer will help me figure out whether you are human or a spam bot. If you're a spam bot I hope your kernel core dumps and your CPU bursts into flames.

   

Please click here to go back to the blog.

blogorama home
about this blog
email the author
where on earth am i?
subscribe to mailing list
feeds Use these links for feed syndication
rss  |  atom
by category
technobabble (60)
philosophical crud (3)
irrelevant stuff (7)
archive
november, 2011 (2)
october, 2011 (1)
september, 2011 (7)
july, 2011 (3)
june, 2011 (2)
may, 2011 (3)
april, 2011 (1)
march, 2011 (1)
february, 2011 (1)
february, 2010 (1)
october, 2009 (1)
september, 2009 (1)
july, 2009 (5)
march, 2009 (2)
august, 2008 (2)
march, 2008 (1)
january, 2008 (1)
september, 2007 (2)
april, 2007 (1)
february, 2007 (2)
december, 2006 (1)
october, 2006 (1)
september, 2006 (4)
august, 2006 (3)
july, 2006 (4)
june, 2006 (3)
may, 2006 (6)
april, 2006 (2)
recent entries
Implementing variab...
Debugging existing...
Screen scraping wit...
Building an Instagr...
Building an Instagr...
Organizing your Jav...
298162 hits