In case you haven’t been following the progress being made on JavaScript 1.8 here’s a quick overview of what’s already landed in the latest Firefox 3 nightlies.

So far, three main features have landed, with a few more to come. In general, this release will be relatively ‘light’, mostly attempting to bring the current JavaScript implementation closer to the desired JavaScript 2 spec.

Expression Closures

This just landed in trunk and I’m sure it’ll tickle those of you who enjoy functional programming. Effectively, this addition is nothing more than a shorthand for writing simple functions, giving the language something similar to a typical Lambda notation.

For example, look at the Lambda notation that’s available in a couple languages, in comparision to JavaScript 1.8.

Python:

lambda x: x * x

Smalltalk:

[ :x | x * x ]

JavaScript 1.8:

function(x) x * x

(For reference) JavaScript 1.7 and older:

function(x) { return x * x; }

I think, probably, my favorite use for this shorthand will be in binding event listeners, like so:

document.addEventListener("click", function() false, true);

Or combining this notation with some of the array functions from JavaScript 1.6:

elems.some(function(elem) elem.type == "text");

This will give you some JS/DOM code that looks downright elegant.

Generator Expressions

This is another one that was just committed to trunk. It’s a little bit more involved than the previous addition, as this one encompasses a number of concepts. Specifically, it requires knowledge of most of the features within JavaScript 1.7, specifically Iterators, Generators, and Array comprehension. This particular feature is based off of the generator expressions that exist in Python.

In the ticket tracking this feature, Brendan posted an elegant, functional, Sudoku solver written using the new syntax that this addition affords us. This demo is based off of a similar one written in Python used to demonstrate its generator expressions.

To better understand what this feature means, lets look at a single line of JavaScript 1.8 code, taken from the Sudoku solver.

dict([s, [u for (u in unitlist) if (u.contains(s))]] for (s in squares))

This line relies upon the dict() function, which takes a 2xN sized matrix, and converts it into a key/value pair object. The code of which can be found here:

function dict(A) { let d = {} for (let e in A) d[e[0]] = e[1] return d }

Let’s go through that line of code, part-by-part, to better understand what exactly is going on.

[u for (u in unitlist) if (u.contains(s))]

The first part of the line is an example of array comprehension coming from JavaScript 1.7. Specifically, we’re iterating over ‘unitlist’ and building it out into an array of keys (excluding which keys don’t contain ‘s’).

[s, ...] for (s in squares)

The second part of this line is another example of array comprehension. At first glance, it appears as if it’s another feature from JavaScript 1.7, a destructuring assignment, although, that isn’t the case. A normal destructuring assignment only occurs when you’re assigning a value, however in this situation we’re just creating an array value using array comprehension. These new 2-unit arrays will then plug back into the dict function.

dict([s, ...] for (s in squares))

This is where the magic happens. In JavaScript 1.7 we could’ve called the dict() function like so:

dict([[s, ...] for (s in squares)])

Note the extra, explicit, use of array comprehension. The issue with that extra comprehension is that it has to be completely run when it’s first encountered, in order to build out the full array (which will then be turned into a ‘dictionary’). However, the lack of extra […] is what makes this a generator expression. That makes that line in JavaScript 1.8 equivalent to the following in JavaScript 1.7:

dict((function(){ for (s in squares) yield [s, ...] ; })())

As you’ll see, it the generator expression lazy-builds the resulting array, handling it as a generator – meaning that the specific values won’t have to be generated until they are explicitly needed by the dict() function (resulting in less loops and better overall performance).

Here’s another example of a generator expression

// Create a generator that loops over an object values function val_iter(obj) { return (obj[x] for (x in obj)); } // Iterate through an objects keys for ( let key in obj ) { ... } // Iterate through an objects values for ( let value in val_iter(obj) ) { ... }

Of course, the val_iter() function could be built with JavaScript 1.7 right now, using yield:

function val_iter(obj) { for (let x in obj) yield obj[x]; }

Most likely, though, generator expressions will see the most use in memory/cpu hungry code (like the Sudoku solver), since solutions will now be able to get results when they need them, as opposed to loading them all up front.