Comments

  1. So-called “iterator-generators” or commonly just “generators” are typically just re-entrant closures with multiple entry points. The fib() example is a classic one, and illustrates the expressive power of “inversion of control.” Let’s look at how you would implement a Fibonacci sequence generator without using generators!

    function Fibonacci() {
    this.i = 0;
    this.j = 1;
    }
    Fibonacci.prototype.next = function() {
    var t = i;
    i = j;
    j += t;
    return i;
    }
    var fib = new Fibonacci();
    for (…) print(fib.next());

    As you can see this is much less expressive than the generator! (Another interesting note for those of you paying attention: the closure’s variables in the generator version are effectively private. Even when doing OOP hacking in Javascript, closures are really the only way to get portable private variables.)

    Generators can also be quite powerful in the same ways that Array.prototype.map() and Array.prototype.filter() can be for composing sequences of operations into one concise bit of code. When writing some really simply image processing software, I had the need for doing things to pixels that were within certain bounding boxes. I did it in Python at the time, but the ideas are very similar:

    /* return every integer (x,y) position within the specified rectangle */
    function rect(left, top, width, height) {
    for (var x = left; x < width; x++)
    for (var y = top; y =left) && (x=top) && (y<=bottom))
    yield [x, y];
    }

    /* Process the intersection of two rectangles (10,10),(15,15) and (8,8),(12,12) */
    for each(var [x, y] in bounded(10, 10, 15, 15, rect(8, 8, 12, 12)))
    someImage.processPixel(x, y);

    See? All we did was add the call to bounded() *around* the call to rect()! The simple concurrency provided by iterator-generators, or “inversion of control,” goes a long way to compartmentalizing code well!

    May 21, 2009 at 5:18 pm |
  2. Uh, somehow my post got ruined. I think I copied and pasted something and lost like, two paragraphs. Oh well!

    May 21, 2009 at 5:20 pm |
  3. Tom Tanner:

    I’m a bit new to javascript, so this code might be considered hacky, but wouldn’t this be a more consistent implementation of the generator

    function Fibonacci() {
    var i = 0;
    var j = 1;

    this.next = function() {
    var t = i;
    i = j;
    j += t;
    return i;
    }
    }

    var fib = new Fibonacci();
    for (…) print(fib.next());

    This maintains the privateness of i and j, and makes the yield look even less pleasant. Maybe there’s a more helpful example somewhere.

    As the the ‘let’ – well, I for one am extremely grateful, as it means the block scoping of names I am used to in so many other languages has become available again, and it makes life sooo much easier.

    October 11, 2009 at 9:30 am |
  4. @Tom Tanner: I think the part of my post that got eaten explained that closures in Javascript are just like objects, having a similar scope chain and such for resolving variable references. Your fib() implementation will probably avoid property lookup overhead on some platforms. On very modern Spidermonkey, the property cache avoids this overhead even with the code in my post. Your technique will have a little overhead in constructing a new closure and instantiating a new function (your next() function.) In terms of overhead, the code in my post probably closely resembles the fib() example given by Ryan.

    I talked about it a while back on the ServerJS list: http://groups.google.com/group/commonjs/browse_thread/thread/6b2f70e57423db36/9f7542b3606db7df?lnk=gst&q=author%3Aviszneki#9f7542b3606db7df

    October 23, 2009 at 11:26 am |

Leave a Reply

You must be logged in to post a comment.