Disfunctional RSS

Where misquotes, misinformation, and misspellings occur daily.

Archive

May
12th
Sat
permalink

Partial Application

My dad once told me there are some things in this world that you can live without…until you get them. This is a truism that gets truer for me every year. I think it has something to do with better technology. Take for instance, an iphone or spotify or streaming netflix. In my dad’s case he was talking about a microwave. Generation gap! Anyways, partial application is one of those things. I certainly use it more than my microwave, and i microwave tons of junk, daily. So what is it? Well, it’s exactly how it sounds: Applying a function partially. Partially in terms of arguments. If have a function that takes, say 3 arguments, we can give it 1 or 2 and get back a new function that only takes it’s remaining arguments. Kind of like “preloading” it with a few or all of it’s arguments. Let’s take a looksee.
var sumOfThree = function(a,b,c) {
  return a + b + c;
};

var needsTwoMoreArgs = sumOfThree.partial(20);
var justNeedsOneMore = needsTwoMoreArgs.partial(30);
justNeedsOneMore(10); // 60
Here, there’s a function sumOfThree that will take 3 arguments and add them together. We begin by giving it it’s first argument, which will return a brand new function that we’ve name needsTwoMoreArgs. Indeed, it does only need two args to complete the call. needsTwoMoreArgs has stored it’s first argument 20 and can’t wait to get the others. Here’s a conceptual representation of that:
function(b,c) {
  return 20 + b + c;
};
So next we partially apply it yet again with 30 and name the resulting function justNeedsOneMore. We call justNeedsOneMore with 10 and finally get a result! We can apply as many as a time as we like:
// two at a time
var justNeedsOneMore = sumOfThree.partial(20, 30);
justNeedsOneMore(10); // 60

// or all three!
var doesntNeedAnyArgs = sumOfThree.partial(20, 30, 10);
doesntNeedAnyArgs(); // 60
Wicked awesome. One thing to note before we go any further. The partial function is not built into vanilla javascript. We’re using osteel’s lib to grab this behavior. Something else you can do is give it an underscore as a placeholder.
var makeBobsName = sumOfThree.partial("Bob", _, "Smith");
makeBobsName("M."); // Bob M. Smith

Currying

Currying is a technique where you return a new function for each argument that’s called - in effect partially applying it each time. So if we have a curried function we don’t have to explicitly call partial each time. In haskell, each function is defaulted to this behavior. I’ve made a little wrapper defn that will do that for your functions as well. It lives in my fork of osteele’s lib https://github.com/DrBoolean/Functional-Javascripts. Let’s play with that!
var sumOfThree = defn(function(a,b,c) {
  return a + b + c;
});

var justNeedsOne = sumOfThree("hell", "o ");
justNeedsOne("world"); // hello world

map(sumOfThree(1,2), [3,4,5,6]);  // [ 6, 7, 8, 9 ]

var sum = reduce("+", 0);
sum([1,2,3,4]); // 10

var getVowels = filter(match(/[aeiou]/ig));
getVowels("so many vowels!"); // [ 'o', 'a', 'o', 'e' ]
The last example is particularly cool. It partially applies match and filter. We’ve done 2 things to be able to write code like this. The first was to make a function called match that takes it’s regular expression first and it’s string second. Then we wrapped in a defn.
match = defn(function(expr, x) { return x.match(expr); });
The string as the second argument allows us to partially apply it without knowing what the data that we’re operating on will be. We’re effectively Separating our data from our functions. That makes for really generic code since we have general functions waiting for whatever data they get rather than first have the data and calling functions on it. It’s no coincidence that the map, filter, and reduce functions take their data second either. This wrapping of native functions isn’t really hard to do. It’s pretty much the same thing each time. I’ve pretty much wrapped all the native functions i normally use (there really wasn’t all that much) and put them on my github in a lib called the prelude. Now we can code like the wild animals we are! But really, I haven’t had any performance issues or namespace collisions so far. We can take it one step further and split them out to mix in appropriately when needed or even pass some argument to qualify the names, but for now, I’m building production apps daily without worry so if it ain’t broke… In the end, partial application is okay on it’s own, but really shines when using together with compose. This can help you fix up arguments so functions compose better…or at all. When we start matching those two up together we get a powerful combination that proves more useful than a microwave.
blog comments powered by Disqus