Starbeamrainbowlabs

Stardust
Blog

EcmaScript 6 Features 3: Generators!

Sorry this didn't come out last week - there is a lot to generators, and I wanted to cover as much as I could. This post took quite a while to put together! Anyway, lets get into the subject of this post: Generators! Generators are a special type of function that return multiple values through the yield keyword (we will get into this in a minute). They can maintain an internal state and return as many values as you like (even an infinite number!). Here is a very simple generator:

function *first_test()
{
    yield "Hello!";
    yield "I am a generator!";
    yield "This is the last thing I will yield.";
}

(gist: todo) Note the asterisk (*) at the beginning of the function name. This is the bit that tells the javascript runtime that the function we are defining is a generator, and not an ordinary function. The next question is how do we actually call the generator? This is actually quite simple:

var test = first_test();

console.log(test.next().value);
console.log(test.next().value);
console.log(test.next().value);

Firstly, we need to create an instance of the generator. This is done by just calling the function normally and storing the result. The technical name for the result we store here is an iterator. To actually extract values from our new generator iterator, we call the next() function on the instance that we created. This returns an object, which contains 2 things:

  1. The next value that the generator yields
  2. Whether the generator is finished

The above isn't very elegant - we can do much better than:

var test = first_test(),
    next = test.next();

do {
    console.log(next.value);
    next = test.next();
} while(!next.done);

The above stores the last yielded result in a variable, outputs the value to the console, and grabs the next result until the generator has finished. Note that if you try to get the next value when the generator has finished, the value will be undefined.

But wait! There is an even better solution to this: a for..of loop.

for(var str of first_test())
{
    console.log(str);
}

The above utilises special for loop construct to create an instance of our generator (remember this is called in iterator) and loop over it's return values until it is finished, all in one! Neat or what?!

This is cool, but generators get better. You could use one to generate IDs:

function *get_id(start)
{
    var current = start;
    while(true)
    {
        yield start.toString(16);

        start++;
    }
}

var id_generator = get_id(100);

for(var i = 0; i < 10; i++)
{
    console.log(id_generator.next());
}

In the above example I am taking advantage of the fact that you can pass parameters to a generator upon creation like any normal function to set the first ID. This Will produce the following:

next id: 194
next id: 195
next id: 196
next id: 197
next id: 198
next id: 199
next id: 19a
next id: 19b
next id: 19c
next id: 19d

Also, this id generator will never complete, so we will always have a source of unique IDs for our program to use.

You can also pass in a single argument when you call next() too. In this way we can create a fancy counter:

"use strict";

function *counter(base)
{
    var number = base;
    while(true)
    {
        number += yield number;
    }
}

var generator = counter(100);

for(var i = 0; i < 10; i++)
{
    let next = generator.next(Math.floor(Math.random() * 10))
    console.log(next.value);
}

The above generator keeps a counter variable and increments it by the amount that is passed in when the next() function is called. In this case, we are passing in a random number between 0 and 10. It might output something like this:

100
101
104
112
114
114
122
125
134
134

This could be useful for maintaining an internal state while serving HTTP requests with Node / io.js perhaps? The possibilities are endless...!

This post was put together with the help of this tutorial: ES6 Generators - davidwalsh.name. This is a really good and thorough tutorial on ES6 generators.

By the looks of the tutorial I followed (link above!), we have only just scratched the surface of ES6 generators. I might have to write another blog about them...

The code I wrote while learning about generators and putting this post together can be found here: https://gist.github.com/sbrl/98cd9bde4d06da5ad5ec

Tag Cloud

3d account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio bash batch blog bookmarklet booting c sharp c++ challenge chrome os code codepen coding conundrums coding conundrums evolved command line compilers compiling compression css dailyprogrammer debugging demystification distributed computing documentation downtime electronics email embedded systems encryption es6 features event experiment external first impressions future game github github gist gitlab graphics hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet io.js jabber jam javascript js bin labs learning library linux low level lua maintenance manjaro network networking nibriboard node.js operating systems performance photos php pixelbot portable privacy problem solving programming problems projects prolog protocol protocols pseudo 3d python reddit redis reference release releases resource review rust searching secrets security series list server software sorting source code control statistics storage svg technical terminal textures three thing game three.js tool tutorial tutorials twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 xmpp xslt

Archive

Art by Mythdael