Generator support in CoffeeScript

    _   _              _    ___  _            _     _                  _
   /_\ | |_ __  ___ __| |_ / _ \| |__ ___ ___| |___| |_ ___   _ _  ___| |_
  / _ \| | '  \/ _ (_-<  _| (_) | '_ (_-</ _ \ / -_)  _/ -_)_| ' \/ -_)  _|
 /_/ \_\_|_|_|_\___/__/\__|\___/|_.__/__/\___/_\___|\__\___(_)_||_\___|\__|
                                                   In Glorious ASCII-VISION
Home

Summary: I added generator support to CoffeeScript, my fork is on GitHub and there's an example webserver ported from Alex MacCaw's JavaScript example in a gist.

Update: I've created a PR for CoffeeScript. I've also just added the yieldfrom keyword which is like ES6's yield* and allows you to include one generator's output in another (here's the commit.)

Update 2: I've also added an iteration syntax.

2013-07-21 Sun: Generator support in CoffeeScript

Generators are a upcoming feature of JavaScript that promise to (amongst other things) really help with callback hell in JavaScript applications. They can be used along with Promises to give a synchronous look to asynchronous code.

The latest version of Node.JS (v0.11.2) added support for generators so it's actually possible to use them now in your Node code.

Alex MacCaw posted a nice example of using generators to write a simple webserver and I thought it would be cool to be able to do that in CoffeeScript.

So I forked the CoffeeScript source on GitHub and added the "yield" keyword to its grammar and code generator. The CoffeeScript version of the syntax I added is pretty similar to the JavaScript version except you don't need to use a special syntax when creating your functions, it will detect if a function is a generator (or not) by whether it uses the yield keyword.

I've put up my changes on GitHub. To try them out you'll need to install Node v0.11.2 ("nvm install v0.11.2") then run the coffee command with using node with the –harmony flag.

node --harmony ./bin/coffee examples/generators.coffee

A simple example of using generators in CoffeeScript:

range = (start, stop) ->
  yield i for i in [start...stop]

o = range(0,3);
// {value: 0, done: false}
console.log(o.next()) 
// {value: 1, done: false}
console.log(o.next()) 
// {value: 2, done: true}
console.log(o.next()) 

And Alex's example webserver ported to CoffeeScript:

sleep = (millis, answer) ->
  deferredResult = Q.defer()
  setTimeout((->
    deferredResult.resolve(answer)
  ), millis)
  deferredResult.promise

app.run Q.async (request) ->
  body = yield request.parseContent()

  console.log('Sleeping')
  yield sleep(200)

  return JSON.stringify(body)

This has just been a quick experiment so it's not ready for production or anything like that but I think generators would be a nice thing to be able to use from CoffeeScript.

Future Work: I think it could do with a nice way of iterating through generators (like Harmony's 'of' keyword) and I've started adding that (without relying on 'of' as V8 doesn't seem to support it yet) but it's sunny outside so maybe later :)

Plug: I'm running a one day JavaScript workshop next week with a couple of other people called JavaScript from Scratch. If you'd like to learn some more JavaScript and you live near London or Brighton in the UK then you should come. We also run a Learn to Code course for people totally new to coding.

 _______________________________________
< follow me on Twitter: @almostobsolete >
 ---------------------------------------
        \   ^__^
         \  (OO)\_______
            (__)\       )\/\
                 || ----w|
                 ||     ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Date: 2013-07-21 22:06:11 BST

Author: Thomas Parslow

Org version 7.7 with Emacs version 23

Validate XHTML 1.0