Iain Lamb · the javascript lambda

February 22, 2009 ‒ 1:19 pm

When I was at Yahoo, I had the pleasure of working with an incredibly bright and articulate group of folks, including Douglas Crockford and Eric Miraglia. A while back, Eric made a post to the YUI blog, describing something Douglas had been teaching called the javascript module pattern.

Slightly restated, this pattern fascinates me – not just as a javascript programmer, but as a computer scientist. At its core, this beauty is a simple anonymous function expression, capable of appearing within itself again and again (because it’s an expression containing expressions):


function (arguments) {

	var	first variable = expression,
		…
		last variable = expression;

	first expression;
	…
	last expression;

}

This concise lambda pattern pretty much describes every block of javascript I’ve written in recent memory – ranging from modest expressions embedded into somebody else’s code to all the way to entire programs. You’re basically looking at source code of every javascript file I’ve produced in the last several years.

Instead of boring you with another power point presentation, this pattern tends to flower into a tree of trees. If the looking glass through which you sculpt source is capable of folding code, you’ll behold an elegant taxonomy, where the perspective of the general is protected from the ignorance of the specific. You’ll walk in a garden where you may prune, graft, demote or promote scope to your heart’s content. As you read, write, and pick your way along the garden path, you may collapse definitions into the void of generality or expand them to the limits of specificity.

An example: I keep the following code under my pillow in a file named iter.js. Along with YUI, it’s an essential member of my standard library. It provides functional iteration:


// :depends yahoo
 YAHOO.namespace('ikl').iter = (function () {
	var	self = {
 		enumerate : function (a, f) {

			// for each ith item in array a, evaluate v = f(i, a[i])
			// stop iteration and return v, if it is truthy

			var i = 0, v = null;
			for (i = 0; i < a.length; i++) {
				v = f(i, a[i]);
				if (v) return v; // stop iteration
			}
		},
 		each : function (a, f) {

			// for each ith item in array a, evaluate v = f(a[i])
			// stop iteration and return v, if it is truthy

			return self.enumerate(a, function(i, v) { f(v); });
		},
 		keys : function(o, f) {

			// for each non-inherited property k of o, evaluate v = f(k)
			// stop iteration and return v, if  it is truthy

			var has = YAHOO.lang.hasOwnProperty,
				k = null,
				v = null;

			for (k in o) {
				if (!has(o,k)) continue;
				v = f(k);
				if (v) return v;
			}
		},
 		values : function(o, f) {

			// for each non-inherited property k of o, evaluate v = f(o[k])
			// stop iteration and return v, if  it is truthy

 			return self.keys(o, function (k) {
				var v = f(o[k]);
				if (v) return v;
			});
		},
 		items : function(o, f) {

			// for each non-inherited property k of o, evaluate v = f(k, o[k])
			// stop iteration and return v, if  it is truthy

 			return self.keys(o, function (k) {
				var v = f(k, o[k]);
				if (v) return v;
			});
		}
	};
	return self;
})();

If you are reading this post on my website using a browser that supports generated content – Firefox, Safari, and hopefully future versions of Internet Explorer – you may explore this example via spring loaded code folding. Just click the top of any block to expand or collapse its content. This view is much like the one I enjoy from my source code editor of choice, TextMate. I like the way it enables you to peruse an expression list at a high level, drilling down into those occasional closures of interest.

The iter.js module is just a fleshed out realization of the lambda pattern I described at the top of this post. Look at the expression to which YAHOO.namespace('ikl').iter gets assigned. Notice the lambda pattern is wrapped in parenthesis. You need to do this whenever you want to call a freshly defined anonymous function on the spot. If you look at the very end of the code, you see the expression is immediately followed by the call syntax – `();` – which has the effect of returning the self object for assignment.

Notice how this code creates an object without using new. Instead, it defines an object literal. Its methods have exclusive access to the bound self variable, rather like a private instance variable.

I almost never use new anymore. I claim instantiation via an object literal returned from a closure provides a more elegant way to associate instance variables with instance methods. I could list a peer variable, foo, after self such that all the functions enumerate, each, keys, values, and iter could get and set it without having to go through a middleman, the reserved this identifier.

On the subject of namespace binding, notice how iter.js has the decency to not clutter the global namespace with any irrelevant symbols. This philosophical courtesy is recursive: enumerate’s variable i now hides from the local namespace of functions that don’t need it, such as iter.each. In fact, it’s now possible for any expressions in higher level functions – your’s included – to iterate over sequences without generating the var i namespace effluvium typical of for loops.

I discuss the deeper meaning of that opening //:depends comment in an earlier blog post. Suffice it to say that when the time comes to use iter.js in another file, I’ll write something like this:


// :depends dom, iter
 (function () {
	var	iter = YAHOO.ikl.iter,
		dom = YAHOO.util.Dom,
		colors = {};

	// assign color labels to rgb values
 	iter.enumerate(['red', 'green', 'blue'], function (i, color) {
		var rgb = Array(3);
		rgb[i] = 'f';
		colors[color] = '#'+rgb.join('0');
	});

	// … maybe some other expressions go here …

	// now create some p elements with colored words
 	iter.items(colors, function (color, rgb) {
		var p = document.body.appendChild(document.createElement('p'));
		p.innerHTML = color;
		dom.setStyle(p, 'color', rgb);
	});
})();

Notice the way I can import modules like Dom and iter as local variables at the top of the block. This makes them available in the discrete namespaces of lower level functions who share calls into the modules over the duration of the module’s closure.

Also, observe how I can pass a lambda right into a function like iter.items. I appreciate the way I can produce these “just in time” functions without having to waste the step of naming them when they are only going to be used once.

Much like iter.js, the outermost closure curbs the proliferation of global variables. It takes a batch of statements that would typically be listed and evaluated in the global namespace and contains them: any variables they define and share become confined to sandbox of the local scope. An interesting difference between the above code sample and iter.js is the way the outermost function isn’t assigned to any variable. It doesn’t need to be. It’s just defined then evaluated on the spot.

By consistently wrapping each block of statements in their own snug closure, the code gains another property: easy conditional or partial evaluation. I can prepend any function call with a true || to deactivate the block or even deep tree of statements within it, easily achieving the same effect as “commenting out” lines of code. I can conditionally execute a block by replacing that true || with a conditional expression. Finally, I can achieve partial execution by using a return statement whenever it’s time to stop. The word “return” has no meaning in the global scope!

I love working with this pattern. It keeps identifiers as close as possible to the scope of the expressions that use them, reducing cognitive clutter and accidental side effects. But more than that, I just like how it feels to write javascript this way. Coding will never be the same.