Javascript Recipe: Partial Application with Iterators

I've read about partial application in Javascript many times, however the concept has always seemed academic and I've rarely applied it to my own code, until recently.

For those who are unfamiliar with the concept, I recommend this article by Reginald Braithwaite on the subject. His definition of partial application is the most concise I've come across:

“Partial application is the conversion of a polyadic function into a function taking fewer arguments by providing one or more arguments in advance.”

What that means is, if you're writing a function that accepts multiple arguments, and your passing in the same argument multiple times, you can cut down on repetition by, well, "providing one or more of those arguments in advance".

Let's take a simple example:

function say(word, person){
    return word+" "+person; 
} 

say('hello', 'Tom'); //returns "hello Tom"
say('hello', 'Jim');  //returns "hello Jim" 
say('hello', 'Bob');  //returns "hello Bob" 

Using partial application, we can cut down on repetition be eliminating that first 'hello' argument.

function say(word){
    return function(person){
        return word+" "+person; 
    }
}

var sayHello = say('hello'); 

sayHello('Tom');  //returns "hello Tom"
sayHello('Jim');   //returns "hello Jim"
sayHello('Bob');  //returns "hello Bob"

In this example, our say() function looks very different. Instead of accepting two arguments, it accepts just one, and instead of returning a string, it returns another function. The magic of partial application is that our new function sayHello() retains access to that outer 'hello' argument.

Using this technique, we can use our say() function to create multiple functions, like sayGoodye():

function say(word){
    return function(person){
        return word+" "+person; 
    }
}

var sayHello = say('hello'); 

sayHello('Tom');  //returns "hello Tom"
sayHello('Jim');   //returns "hello Jim"
sayHello('Bob');  //returns "hello Bob"

var sayGoodbye = say('goodbye'); 

sayGoodbye('my love');  //returns "goodbye my love"

A Practical Application of Partial Application

The above example illustrates the point, but it doesn't really apply to real-world web development much.

Let's take a more practical example:


var i=0; 

function iterate(){
    i++; 
    console.log(i); 
}

setInterval(iterate, 1000); 

The above code just increases the variable i every second and outputs the result to console.log(). I was experimenting with the audio api recently and had to use setInterval() with an iterator just like in the above example.

The problem with the above example is that, if you declare the i iterator outside of the iterate function, it means you can't use the i variable anywhere else. Watch what happens when you do:


var i=0; 

function iterate(){
    i++; 
    console.log(i); 
}

setInterval(iterate, 1000); 

for (var i=0; i<10;i++){
    console.log('inside a loop', i); 
}

By the time setInterval starts, the value of i is 10. The simple solution would be to just not use the i variable anywhere else, but I like using i for iterators, so instead, we can use partial application to declutter our variables.

Behold:

function createIterator(i){
    return function(){
        i++; 
        console.log(i); 
    }
}

var iterate = createIterator(0); 

setInterval(iterate, 1000); 

Using partial application, we can properly encapsulate the variable i inside our iterate() function, and every time that function is called, the variable i will increase without interfering with the outside world.