May
12th
Sat
12th
Composition
Composition is a fancy name for passing the result of one function as an argument into the next function. If we have some functions like these:
add2 = function(number) {
return number + 2;
}
subtract1 = function(number) {
return number - 1;
}
We could do this:
addSubtract = function(n) {
var addedValue = add2(n);
return subtract1(addedValue);
}
Or We could do this:
addSubtract = compose(subtract1, add2);Both would yield 4:
addSubtract(3); // 4compose makes a brand new function. The data flows from right to left applying each function along the way. Right to left makes sense when you think about the parenthesis going to the right of the newly constructed function. Here’s another few examples
dasherize = compose(join('-'), split(/\s+/g);
dasherize("Big Al's Trucks"); // "Big-Al's-Trucks"
doFunkyThingsWithName = compose('.toUpperCase()', reverse, '.name')
doFunkyThingsWithName({name: "George"}); // "EGROEG"
The combination possibilities are endless. We can compose groups of functions that go together into little programs. Then we can even compose those programs!
Checkout how easy it is to play around:
var loggingFun = compose(log, subtract1, log, add2); loggingFun(3); // 5 // 4 // 4 var memoizedFun = memoize(loggingFun); memoizedFun(4); // 6 // 5 // 5 memoizedFun(4); // 5 var newProgram = compose(otherProgram, memoizedFun); parallel_compose(thirdProgram, newProgram);Why is this so amazing?
No data
You may notice I don’t need to name any intermediate results. This is a big deal. This assists in separating your data from your functions since you simply don’t see the data. I think a lot of people are turned off from functional programming by the thought of juggling arguments (data) around all the time instead of tucking them away in a nice object. Here, there is no data at all, rather functions plugged together to work on anything. This gives you megagenericicity which is a word i just made up. Starting from the original data call, we just start composing away.
UsersController = (function(){
index = db.all('users', compose(renderView, manipulateUserData));
return {index: index}
})();
Build up from smaller functions
Is it a surprise to find out most of what you write is the same stuff over and over again? Instead of writing out the same function calls with different names or the same assignment statements to different variables, you can skip all of that and just drop the function name in. The code drops in size, becomes more generic, and you distill the code to just the important behavior. If you’re worried about names missing since names give you an idea of what we’re operating on, don’t sweat it - just assign a specific name to each function:
// no one says it has to be like this:
getArgNames = compose(last, match(/\((.*)\)/), first, split('\n'));
// it can easily be like this:
firstLine = compose(first, split('\n'));
contentInsideParenthesis = compose(last, match(/\((.*)\)/));
getArgNames = compose(contentInsideParenthesis, firstLine);
Smaller functions that do one thing means more reusable parts. Taking advantage of the divide and conquer strategy, we can build very complex systems with easy to grok simple functions.
Turns out, lots of the smaller functions you break out can be put in to utility libraries and moved out of your application code. This technique promotes reusability (common theme here…) and makes your app simpler.