

Generator (yield keyword) support in CoffeeScript for Node.js - almost
http://almostobsolete.net/coffeescript-generators.html

======
jashkenas
Lovely work, and it looks like it wasn't too difficult to add:

[https://github.com/jashkenas/coffee-
script/pull/3078/files](https://github.com/jashkenas/coffee-
script/pull/3078/files)

If anyone wants to chime in on the pull request itself, input is welcome --
particularly about how to address the conflict with the usual "compiles to
JavaScript that runs anywhere" ethos of CoffeeScript. If we're going to start
moving past that, "yield" is a fine place to start.

~~~
wycats
There are going to be some bigger issues if you start targeting ES6, like the
inconsistency between for/of in ES6 vs. CoffeeScript, differences in
destructuring, semantic inconsistencies in classes, etc.

I'd be very interested to see a proposal for how to deal with that moving
forward for CoffeeScript. Will CoffeeScript:

1) ignore new ES6 features that have syntactic overlap with existing
CoffeeScript features

2) leave the existing syntax alone and create new syntax that targets the ES6
syntax (for/of means CoffeeScript for/of, while for/inside means ES6 for/of)

3) break backwards compatibility and release a CoffeeScript 2 that targets ES6
and doesn't use syntax that could conflict in the future

There may be another option, but I can't think of it. Knowing exactly which of
these options CoffeeScript will take will give me a better understanding of
the long-term viability of CoffeeScript.

~~~
jashkenas

        > Knowing exactly which of these options CoffeeScript will take 
        > will give me a better understanding of the long-term viability 
        > of CoffeeScript.
    

Mmm, nothing like the whiff of uncertainty on a summer evening ;) For
starters, you needn't worry -- CoffeeScript already being a heavily forked
open-source project, I'm sure there will be versions (whether Coco, Live,
Iced, Gorilla, or perhaps a cutely named CoffeES6cript) that track each of the
options you've listed.

But you asked about my proposal. I'm most interested in targeting the useful
subset of JavaScript that runs across the popular JS platforms at any given
moment -- not what may or may not exist in the future, but lives currently as
a spec; and also not features that actually exist, but aren't essential (read,
harmful, error-prone, nasty), like getters and setters, or E4X (in my opinion,
natch).

So in general, what I'd like to see mainline CoffeeScript do, is adopt useful
ES6, ES7, and ES8 features, as soon as they land in enough platforms/browsers
to be widely useful (yield may be at this point already, or very soon), and to
continue to try and find a pleasing minimalist syntax for writing and reading
them. If this means taking the ES* syntax wholesale, that's fine. If it means
minting a new (and hopefully, but arguably, nicer) syntax, that's fine too.
And if it means breaking backwards compatibility, that's also alright, as the
compiled lowest-common-denominator JS output will still be perfectly
compatible with the new stuff.

~~~
apaprocki
Thankfully E4X doesn't actually exist anymore (as of FF 21) :)

------
olegp
Alternatively you could use fibers. We've been using them together with Common
Node ([https://github.com/olegp/common-node](https://github.com/olegp/common-
node)) at [https://starthq.com](https://starthq.com) with great success -
running smoothly on an EC2 micro instance with 300+ concurrent users on site.

~~~
SeanDav
I have been quite interested in using fibres. I have concerns about
compatibility with existing libraries, stability etc.

Could you point to some documentation/discussion/blogs/anything that addresses
these concerns and provides decent examples of use?

~~~
olegp
Here's a talk I gave on the topic:
[http://vimeo.com/32507674](http://vimeo.com/32507674) and here are the
slides: [http://www.slideshare.net/olegp/js-
everywhere-2011](http://www.slideshare.net/olegp/js-everywhere-2011)

Feel free to message me on Twitter (@olegpodsechin) and I'd be happy to answer
any questions you have.

------
bayesianhorse
Great idea. Generators are one of the features that still seperate
coffeescript from python, in terms of productivity/elegance.

Still missing is a syntax to consume these generators, like in "for a in b" or
"yield from"

~~~
almost
Definitely agree with need for iteration syntax and yieldfrom keyword. The
iteration syntax will probably have be something different than "for a in b"
because that's already used for array-like iteration and adding another case
would slow existing code down (all of which wouldn't be using it of course).
For yieldfrom the code it needs to generate is something like this:

    
    
        var generator = g1(), result = {}, send;
        while(!result.done) {
            result = generator.send(send);
            send = yield result.value;
        }

~~~
bayesianhorse
I would suggest "for a from b". If that only uses .next and .send, it might
work with class instances too, like the iterator protocol in Python.

~~~
almost
I've found one problem with that syntax: people use variables named "from"
quite a lot in code already (including all over the coffeescript source)

------
csense
Does this work when compiling code to run on the browser?

If not, how could you modify the Coffeescript compiler to make that happen?
(Preferably without requiring browser makers to make any changes.)

~~~
almost
It's possible using two techniques called continuation passing transform and
trampolines[1]. The downside is that the produced code would be a bit ugly and
one of coffeescript's selling points has always been that it produces sensible
code.

[1]:
[http://en.m.wikipedia.org/wiki/Trampoline_(computing)](http://en.m.wikipedia.org/wiki/Trampoline_\(computing\))

------
wycats
Does this mean that the mere presence of the word `yield` turns a function
into a generator? Is there any way to build a yield-less generator (say, a
noop generator for an API that requires a generator)?

~~~
almost
Yes it does.

If you did want a generator that didn't yield anything I guess you could
write:

    
    
        myEmptyGen = ->
          yield if false
    

Which is pretty ugly, but it's not something I've needed to do often with
generators (in Python at least)

------
almost
I just added yieldfrom (like yield* in ES6, includes the output of one
generator in that of another) support in a separate branch:

[https://github.com/almost/coffee-
script/commit/67f2347685b45...](https://github.com/almost/coffee-
script/commit/67f2347685b450eb5ae0a1d0ead73c5e6dce0273)

