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;
}
"for of" is actively being added to V8. It should not be very long before it lands in V8 (and thus in Node). I don't like the idea of another keyword that at best acts exactly the same (or at worst acts subtly different).
CoffeeScript already has an of operator (like js in) and an in operator (array like iteration) neither of which could easily be made to both (I think). So we'd probably need a new name. Once "of" is in V8 we can compile to it directly though.
It's not clear to me how to compile directly to it without breaking CoffeeScript code that already uses for/of. Is the idea to break compatibility with existing CoffeeScript code?
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.
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.
Even if CoffeeScript doesn't support ES6 features it will still be a useful in the long term. I'm betting ES3 code generated by CoffeeScript will run fine in a ES6 runtime.
With that said, I'm happy to lose backwards compatibility in lieu of ES6 support. We've already seen forks like IcedCoffeeScript before.
It should be a major jump though, with a migration guide at least. It's similar to the 1.8.7 -> 1.9.2 jump. It's painful, ugly, but for the greater good.
> 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.
I'd love to see #3. As a user of a language, moving targets are a hassle. It would be clear as day if it was stated that existing CS 1.0 === ES5 (or whatever), CS 2.0 == ES6. This unshackles those working on CS to really fundamentally take advantage of the new features. (Isn't this spirit what drove CS in the first place?)
Alternatively you could use fibers. We've been using them together with Common Node (https://github.com/olegp/common-node) at https://starthq.com with great success - running smoothly on an EC2 micro instance with 300+ concurrent users on site.
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)?
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.
28 comments
[ 3.6 ms ] story [ 57.3 ms ] threadStill missing is a syntax to consume these generators, like in "for a in b" or "yield from"
I've almost got yieldfrom working...
See my longer question about this upthread.
> Update: I've created a PR [pull request] for CoffeeScript. I've also just added the yieldfrom keyword...
Maybe this update happened after your comment?
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.
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.
With that said, I'm happy to lose backwards compatibility in lieu of ES6 support. We've already seen forks like IcedCoffeeScript before.
It should be a major jump though, with a migration guide at least. It's similar to the 1.8.7 -> 1.9.2 jump. It's painful, ugly, but for the greater good.
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.
For many use-cases, this is a good enough reason to use them.
Could you point to some documentation/discussion/blogs/anything that addresses these concerns and provides decent examples of use?
Feel free to message me on Twitter (@olegpodsechin) and I'd be happy to answer any questions you have.
If you did want a generator that didn't yield anything I guess you could write:
Which is pretty ugly, but it's not something I've needed to do often with generators (in Python at least)https://github.com/almost/coffee-script/commit/67f2347685b45...
If not, how could you modify the Coffeescript compiler to make that happen? (Preferably without requiring browser makers to make any changes.)
[1]: http://en.m.wikipedia.org/wiki/Trampoline_(computing)