In my latest dispatch on JavaScript, I describe some curious ways to decompose your program into functions that return functions. This technique seems to promise programs that are structured into more cohesive and smaller pieces, and the process of coding accordingly sure feels like working from the specific to the general. Plus I produce, among other things, a possibly gratuitous example of currying in JavaScript.
I’ve been prototyping some drag and drop interactivity and CSS stylesheet toggling for a new client, and I find that event handlers continue to be rich opportunities for exploiting JavaScript’s closures (every function is a closure) and lexical scoping (variables bind at the time of function definition). For example, let’s assume that I have defined a nice helper function to handle differences in browser implementations of event handling:
addEventListener(html_element, action_name, func)
Then I can set up an action to take place when a user clicks on an HTML DIV
element, like so:
addEventListener(target_div, "click", function() { elements_set.each(function(elem) { elem.disabled = (elem.id == target_div.id) ? false : true; }); });
The anonymous function created above loops through a set of elements and disables each unless it is the target div, the div that has been clicked. The code is nothing fancy, nothing to brag about. It’s just nice that the anonymous function, which hangs around until it’s time to be executed, “remembers” the value of target_div
and elements_set
. No need to do any inspection or discovery at the time of execution: the scope in which the function was defined is right there with it, waiting like a seed to sprout when the time is right.
I’ve found that this “remembering” can allow you to decompose the tasks of your program in interesting ways. For example, let’s say that the call to addEventListener
above is part of a function that sets attributes for the DIV element whose onclick event we’re watching for:
var addElem = function(options) { var target_div = document.createElement("div"); // some code that sets up the target_div parent_div.appendChild(target_div); addEventListener(target_div, "click", function() { elements_set.each(function(elem) { elem.disabled = (elem.id == target_div.id) ? false : true; }); }); return target_div; };
Why does this function return the DIV element? So that I can call addElem in this context:
function proc_to_add_elements_to(div) var elements_set = $A(); var addElem = function(options) { // as above, but note this line within: parent_div.appendChild(target_div); return function(options_list) { options_list.each(function(options) { elements_set.push(addElem(options)); }); };
Whee! This is actually fun to write.
- This function takes a reference to the HTML DIV object to which our
target_div
elements will be added: this is whereparent_div
comes from. - So first I set up an array called
elements_set
. - Then I define
addElem
, which includes a reference toelements_set
, which is empty at the moment but won’t be when the event handler defined withinadd_choice
executes. - Then I return an anonymous function that will (someday) take an array of options hashes, use
addElem
to take each hash and create an element and its event listener, and add that element intoelements_set
.
So we’re building a structure of functions, each of which returns a function that just needs a little more information to execute. I was tempted to write that I’m deferring execution or binding, but of course that’s not so: when the top-level function executes and starts calling this structure of functions, it will execute top-down. But the coding I’m doing is bottom-up, and from this perspective, I am delivering specific functions to more general ones.
So, now I’ve got myself a function proc_to_add_elements_to()
, which is named as such because it returns a procedure for adding elements to the DIV
you pass in. And that returns a function ready to take a list of options.
I admit, this is kind of overkill. Why not pass the parent DIV
and the options list? Well, two reasons, one valid, one utterly gratuitous. Here’s the gratuitous one first:
Because this structure is currying!
var activate = proc_to_add_elements_to(column1); activate( [ {'id': 'preferred contrast', ... 'disabled': false }, {'id': 'high contrast', ...} ] ); activate = proc_to_add_elements_to(column2); ...
A better reason is that there are scenarios in which a two-step process produces more readable or more efficient code. For instance, suppose you actually had to do some work to determine which element would be the parent_div? You could evaluate code (even another anonymous function) between the parentheses of proc_to_add_elements_to
, and it would be easier to read without another multiline set of code immediately following. Or, perhaps you want to create an array or hash of functions and then call one depending on runtime conditions. You can call proc_to_add_elements_to
repeatedly, placing each anonymous returned function into that array or hash for later use.
I mentioned bottom-up programming, which is a popular buzzword, or buzz phrase I guess. I’m excited because the function-oriented programming I’ve been doing lately feels bottom-up whether or not Paul Graham would describe it thus. It seems to separate pieces of my problem space very nicely, and it gives me functions that almost read like English, e.g. the top-level function activate
that takes as an argument a hash of options for the objects that will be created. And that’s all the code in the function. Chad Fowler has said Ruby methods shouldn’t be more than four lines long. He’s kind of joking, but he kind of isn’t. If you use functions that return functions to decompose your problem space, you might actually have a shot at four-line functions that actually make sense the first time you read them.
In another post soon to follow, I will point to more impressive work others are doing to explore JavaScript’s functional programming capabilities and to make JavaScript behave like Ruby.