JS Trickshot: Generator Expressions

It's time for another short article in my 'trickshot' series. Today, I'll dip into JavaScript code. But beware, this is not only a blog post about a language trick. It's a little rant about node.js and v8 as well.


I'm no JavaScript guru. However, I wrote quite a few applications in JS, ranging from "the good old web-apps" up to device-specific apps. Even a small data visualization app using XULRunner. I used node.js in the past (for file/image processing purposes) and I use it today as well. Now, the thing is: With this (little) experience of a year with Node, I'm starting to really dislike the whole concept of Node.

I'm not going to dive in further about my reasons for not liking it. I just want to lay out that in my opinion the fact that Node is based on v8 and is forcing me to stick to inappropiate server-side single-threaded event-loop is a big step back to stampcard engineering.

It shouldn't be that way. JavaScript has a vibrant community and with the rise of HTML5 JavaScript really can become a serious (albeit sick) option for frontend engineering. Even more, recent developments on JS really show that we generally head to the right direction.


Generator Expressions

One of those little known innovations surely is the development of the JavaScript language itself. Since I had to dive in a little deeper into JS last summer for a small project, I discovered some neat features I wasn't aware of. One of those features is called generator expressions.

The python people now surely know what this trickshot is going to be. Generator expressions are a nice way of creating sequences and even do some mapping and filtering on them. Before we look at generator expressions, let's first build up a small range generator with the yield feature:

var range = function(s,e){
  for (var i=s;i<=e;i++) yield i;

Now that we have a simple range sequence generator using yield, we could just iterate over it and display the sequence:

for (var i in range(1,15))

Good thing. Now, if we'd like to materialize the sequence of range(1,15), we could preinitialize an array and just push the values into the array instead of logging. Something similar to this:

var a = [];
for (var i in range(1,15))

Looks fairly straight-forward. However, we could materialize our range much easier by using array comprehensions:

var a = [i for (i in range(1,15))];

This is much better. Simple, terse, readable. Array comprehensions even allow us to modify and filter the materialization on the fly easily. Say you want the square of all evens from our list. Piece of cake with array comprehension syntax:

var a = [i*i for (i in range(1,15) if (i%2==0)];

Nice. Now let's finally get to the feature we were looking at from the beginning: generator expressions. Generator expressions are very similar to array comprehensions. The important difference between both is that generator expressions don't materialize to arrays. This is a very powerful feature since it allows us to write space and time-saving code.

Let's make another little example for illustration. We want to compute the square and the factorial for the evens of a specific range. We can define this easily with generator expressions:

var fac = function(x) x>1 ? x*fac(x-1) : x;

var squares = (i*i for (i in range(1,50) if (i%2==0));
var facs = (fac(i) for (i in range(1,50) if (i%2==0));

The squares and facs definitions look much like array comprehensions, except we used braces instead of square brackets. The real difference however is that both squares and facs are no arrays but real generators.

This means that effectively no square or factorial is being calculated in the above example. The first calculation occurs when the first value of square or facs is being requested. Again, this is no news for people from python land and the C# lovers out there can easily think of generator expressions as a simplified LINQ .Where() and .Select() syntax.

JavaScript Innovation Land

I think the above examples show how new language features can help to write better - that's more powerful and readable - code in JavaScript. Actually, these language innovations are only one perspective on how many wonderful things happen in JS land. I for one have a solid impression that it's at least very unfortunate that node.js bigots and unreasonable hysteria on the 'server-side JS revolution' obliterate many thoughtful innovations.

I'm well aware that above "trickshot" could surely reraise the old ECMAScript is no JavaScript discussion for a few JS devs outs there. Yes, the above language actually is JavaScript. And yes, I'm aware it only runs on Mozilla, although some of the above features are in ES.Next. My intention surely is not to fire up such a discussion but instead show this specific field of innovation in JavaScript ecospace as an example to the many cool things happening nowadays regarding JavaScript.

(c) Copyright 1998 - 2014 Ilker Cetinkaya.