Open lolmaus opened 9 years ago
A few notes, You're comparing ES6 using ES5 as an example:
for (var key in props) {
if (!props.hasOwnProperty(key)) { continue; }
}
// VS
Object.keys(props).forEach(function(key) {
var value = props[key];
}
With that said the design goal of CoffeeScript is to support all browsers down to ES3 (enter IE6 stage left). Because of that any ES6 is incompatible with ES3 syntax. The only way to by pass this is with backticks. This is expected as CS was designed to trans-pile to JavaScript which needs to be compatible.
For now backticks are the way to manage this and I use them in my Ember-CLI project which is an es6-transpiler project. It is likely that in the future as the rest of the world finally moves from the old JavaScript and ES6 gains more traction that CS will diverge and there will be an CoffeeScript 3 version and a CoffeeScript 6 version. I doubt this will not be driven by the core CoffeeScript dev team but instead by a forked team.
Anyway enough speculation. I feel the goal of this Cook-book project is to offer patterns / recipes for such a case when a user wishes to use some of the ES6 syntax in the current version of CS. An example might look like:
`import Ember from 'ember'`
`import MyModule from '../my-module'`
MyClass = Ember.Object.extend
foo: "bar"
baz: -> "baz"
`export default MyClass`
It might be worthwhile separating out the syntax issues from semantics/polyfill issues.
So array comprehensions are syntax (alas not in es6 but still supported in some of the transpilers) but a lot of the improvements in JS objects/Arrays/iterables etc not syntax and are available to CS. Modules are sorta in the middle and easily managed with backticks or direct use of SystemJS.
This would help me just understand how bad it would be to just jump to es6! Array Comprehensions still are huge for me.
James Long (@jlongster) had a nifty suggestion for the TC39 committee: when considering a change in syntax to Javascript, build a SweetJS Macro of it for testing. I'm wondering how hard it would be to do that for any much-loved CS syntactic feature not in ES6? Build macros for them?
Then we'd be OK with es6 itself, filling in with Sweet macros any features we badly miss.
For the rather mind-numbing discussion about this very topic check out issue jashkenas/coffeescript#3162.
I found I mostly agreed with the following quote from @bjmiller:
The most important feature of ES6 is still not implemented anywhere, and is likely to arrive last because it doesn't change/affect syntax and is apparently harder to do than I think: Tail call optimization. The most divergent (and, widely in use already) feature in ES6 is generators, and the next release of CS will have full support for them.
ES6 modules are kind of terrible, and no one can figure out why the TC didn't just use CommonJS, which everyone loves. Browserify handles modules and modularity better than the ES6 "modules" feature for the client side, and any use cases that fall outside of what Browserify does are probably handled well by Webpack.
So much of ES6 is straight up hype. "Solutions" that we've already solved ourselves by building libraries, or which only solve problems that come out of a textbook on computing theory.
With all that said, a small subset of ES6 things should probably be allowed to "pass through" to JS without the use of backticks, because some people will be happier that way, and everyone else can just ignore it. Especially if it's easy to implement, with no special syntax. But, even if it isn't, CS still does what it does very well, and you can build anything that you need using it.
ES6 will be obsolete before CoffeeScript is.
Hi @lolmaus, you told "Some of core CS features conflict with ES6, namely backticks and fat arrows", but reading http://6to5.org/docs/learn-es6/#arrows we see "Arrows are a function shorthand using the => syntax. They are syntactically similar to the related feature in C#, Java 8 and CoffeeScript. They support both expression and statement bodies. Unlike functions, arrows share the same lexical this as their surrounding code." Is this not exactly the CS fat arrow behavior?
In the example we can see:
v => v + 1;
(v, i) => v + i;
v => {
if (v % 5 === 0)
fives.push(v);
};
I sure could rewrite this in CS as:
(v)=> v + 1
(v, i)=> v + i
(v)=>
if v % 5 is 0
fives.push(v)
So... I don't see a problem to translate CS's =>
to ES6's =>
About the backticks (Template Strings), i don't see any problem. CS has a way better design in this area. While JS has '
and "
with the same meaning, CS has '
as a JS equivalent (plus multiline) string definition; "
as a multiline template string (exactly like ES6 backticks); and backticks with a transcendental meaning like we have in Ruby, Perl, PHP...
I don't see any problem in translating CS's double quote to ES6's backticks, on the contrary, that is much better to my keyboard, and to the coding culture.
I believe CoffeeScript needs a "target
parameter", or a "feature translation configuration", allowing us to compile CS to old JS or bleeding edge JS, or also to special environments.
So, is there a real translation problem between CS and ES6 or is this only a FUD?
@aurium,
Compiling CS fat arrow to ES6 fat arrow will be a breaking change. The awesomest feature of CS fat arrow is being able to reference both local scope via this
AND outer scope via this
. This is impossible with ES6 fat arrow.
As for backticks (and other constructs including the fat arrow) is that they mean different things. It's fine for CoffeeScript, but if we start a new preprocessor, we should embrace the ES6 syntax and use other syntax constructs for preprocessor features.
@bjmiller in the CoffeeScript thread has stated an awesome idea, you should totally read his original comment.
For the features that have syntax conflicts between CS and ES6, CS does a better job. A CoffeeScript coder will never feel a need in those ES6 features.
this
the shit out of 'em?class
?this.foo = foo
in the constructor?Other features either don't conflict with ES6 syntax or can be passed through backticks.
Also, it makes perfect sense to use CoffeeScript AND a ES6 transplier like 6to5. Or you can use libraries like RSVP to have more powerful alternatives to certain ES6 features.
Can anyone name a feature where CoffeeScript falls short?
Heh. Good thing workflow tools (Gulp etc) handle transpilation so well. I doubt there are many of us willing to give up both CS and ES6. And because TC39 is headed to yearly editions, we'll seldom use vanilla JS, there'll be yet another ESnext.
On Fri, Jan 23, 2015 at 12:48 PM, Andrey Mikhaylov (lolmaus) < notifications@github.com> wrote:
@aurium https://github.com/aurium,
Compiling CS fat arrow to ES6 fat arrow will be a breaking change. The awesomest feature of CS fat arrow is being able to reference both local scope via this AND outer scope via
this
. This is impossible with ES6 fat arrow.As for backticks (and other constructs including the fat arrow) is that they mean different things. It's fine for CoffeeScript, but if we start a new preprocessor, we should embrace the ES6 syntax and use other syntax
constructs for preprocessor features.
@bjmiller https://github.com/bjmiller in the CoffeeScript thread has stated https://github.com/jashkenas/coffeescript/issues/3162#issuecomment-70960807 an awesome idea, you should totally read his original comment.
For the features that have syntax conflicts between CS and ES6, CS does a better job. A CoffeeScript coder will never feel a need in those ES6 features.
- Rest and sperad? What a weird way to call splats.
- Fat arrows? Oh, you can't pass them as callbacks to libraries, because some libraries fucking bind callbacks to objects and suppose you this the shit out of 'em?
- Multiline strings? Without interpolation?
- Destructuring assignment? But you can't use it to assign instance attributes in class?
- Classes, you say? Oh, but you can't define properties, only methods, and still have to do this.foo = foo in the constructor?
- Comprehensions? Don't make me laugh!
Other features either don't conflict with ES6 syntax or can be passed through backticks.
Also, it makes perfect sense to use CoffeeScript AND a ES6 transplier like 6to5. Or you can use libraries like RSVP to have more powerful alternatives to certain ES6 features.
Can anyone name a feature where CoffeeScript falls short?
— Reply to this email directly or view it on GitHub https://github.com/coffeescript-cookbook/coffeescript-cookbook.github.io/issues/128#issuecomment-71253704 .
The awesomest feature of CS fat arrow is being able to reference both local scope via this AND outer scope via
this
.
I'm not trying to be offensive but this doesn't feel like a feature to me. The mixing of CS and JS to handle scope suggests a abuse of the language. Why not set a variable at the correct scope level instead of swapping @
and this
(back ticked).
This is defiantly a code smell and if used needs refactoring.
For the features that have syntax conflicts between CS and ES6, CS does a better job. A CoffeeScript coder will never feel a need in those ES6 features.
Oh I like these, Spot on.
@sukima .. oh gawd, thanks for explaining the (kinda cool) difference between @ and this
.. depends on context. Er..not that I'd dream of using it! :)
Regarding your first point:
- Collect references to and discus JS preprocessors that implement CS-like syntax while maintaining ES6 compatibility. I failed to google up any but maybe you're luckier.
Might I suggest LiveScript? http://livescript.net/
Thx for your contribution, @sleepyfox.
LiveScript is the only preprocessor i'm aware of that possesses the spirit of CoffeeScript and has a large community. But their ES6 status is identical to that of CoffeeScript. The only difference is that LiveScript haven't closed their ES6 issue ticket, but it's as inactive as CoffeeScript's.
I no longer think that lack of support of native ES6 syntax in CoffeeScript is a pitfall. As i said above, it's not necessary. Also, CoffeeScript has just added support for generators, so it's not forever stuck in ES3 as it seemed before.
I thought of writing an article to coffeescript-cookbook.github.io that compares ES6 features and their CoffeeScript alternatives. Do you guys think it's worth doing?
What is in ES6?
So all in all, there's really no reason to drop LS for ES6 as far as I can see, and CS supporting Generators really just means more options for people.
Oh, and yes, I do think it is worth doing writing an article comparing CS to ES6 features, the more people are informed about this stuff the better off we will be.
Also missing get and set literals for classes.
For anyone who is interested in a comparison of CoffeeScript and some of the things coming in ES6, I wrote an article to show some of the differences in syntax.
This is going a little off topic but the lack of getters and setters syntax can be worked around by using Object.defineProperty
and Object.defineProperties
. Not as cool as language support but the functionality is there. This is a kin to es6 modules support via back ticks. Personally I don't see the rush to es6. It's not like this stuff is here today gone tomorrow, Hell look at how long it took to finally say goodby to IE6 and were still stuck at es3 with IE8. We have years to worry about this cruft. Well, that's just my humble opinion.
I remember from my old Java programming days that using getters and setters was considered a code smell and violated the "Tell, don't ask" rule...
@sleepyfox in general I would agree, especially in most code example on getters and setters. However there is a time and place for them. For example when writing a library where you need to manage change events. An example would be Backbone where it's API requires all assignment and fetching to be done with set()
and get()
this is to allow the Backbone system to send change
events to anyone listening. The advantage is that the application can be data driven instead of DOM driven like most jQuery based pages. Now contrast that to say Ampersand who adds the getter and setters notion. myModel.myProp = 'foo';
will cause a change
event because myProp
is actually a setter.
So yes it can be abused and violate the "Tell, don't ask" but in the above example you are telling it to set a property who's side effect is intentional, well known, and expected. In conclusion, there is a time and a place for them even if most examples don't teach when and where and instead tend to insight code smells.
It is pretty simple to wrap state in a closure (use the module pattern) and prevent anyone fiddling with your object's properties. That way you can enforce your class's contract.
I found another ES6 feature that is impossible with CoffeeScript, at least without too much scaffolding: private properties.
Demo: http://goo.gl/juKxyx
Also, async/await: http://goo.gl/wnQS4j (Is IcedCoffeeScript still alive?)
@lolmaus really? I do three impossible things before breakfast, behold!
class Person
constructor: (name) ->
person_name = name
@get_name = -> person_name
Bob = new Person('Bob')
alert Bob.get_name() # = 'Bob'
alert Bob.person_name # = undefined
Alternatively you can instead apply Crockford's 'module pattern' and use factory functions like so:
makePerson = (name) ->
do ->
secret_name = name
visible =
get_name: -> secret_name
Bob = makePerson('Bob')
console.log Bob.get_name() # = 'Bob'
console.log Bob.secret_name # = undefined
I hope this helps.
@sleepyfox, a number of issues with your approach:
class
directive as intended. You have to write all your instance methods inside the constructor method, otherwise they will not close over your private property. This makes the code harder to read: you have to spend time and effort just to grasp what's going on there. @lolmaus
The reality is that JavaScript is not Java, nor is it C#, C++ or SmallTalk. Objects do not work the same way, and inheritance works in a very different way (i.e. Self's prototypical version) than other so-called OO languages. Part of learning how to use JavaScript effectively is in knowing what works, and what doesn't. Trying to write C++ or C# using JavaScript, just because there is thing called Object
, or trying to write Java code in CoffeeScript just because there is a thing called Class
is an anti-pattern.
Personally I wish @jashkenas had called it something other than Class
because I think it gives the wrong impression, but we are where we are.
Hey @sleepyfox, i agree with your reasoning (except for 5: it ruins TDD).
Bu you're mixing two different things here: language capabilities and best practices.
The fact that you're able to shoot into your leg does not mean that gun manufacturers should make it impossible to shoot into legs. Sometimes shooting into a leg is what you need from a gun.
In much the same way, sometimes you do need to deliberately monkeypatch a class. Sometimes you need to simply add a method to a single instance of a class, and that method should have access to that instance's private properties. Sometimes subclassing is the way to go (and it is very often, even in JS. Have a look at Ember).
A JS preprocessor should never limit a user in what he's able to do with JS.
@lolmaus OK, let's agree to disagree, about testing private methods, sub-classing and monkey-patching.
Guns: remind me never to stand near you on a range.
As far as what a JS pre-processor should or should not do, I think that's really the purview of the person who writes the pre-processor. If we disagree with their premise, we're perfectly capable of writing our own.
Going back to the original point: you said private properties were impossible with CoffeeScript; I showed you two different quite simple ways that they could be implemented, and I'm sure there are more.
In most cases I have observed encapsulation is well enough served by closures and modules to make the need for secure private properties or methods moot. YMMV.
Fun discussion but this is totally off-topic for the coffeescript cookbook
Would like to close this issue. Thoughts?
It indeed does not relate to the cookbook directly, but this project is a community of CoffeeScript enthusiasts, people who should be worried with the indeterminate future of CoffeeScript.
Unless we've got strict policy for the issue queue, i suggest we keep this open for discussion.
With the addition of generators to CoffeeScript (something that forks like LiveScript have been working with for some time) the last major reason for thinking of swapping to ES6 has been removed for me.
I love CoffeeScript and i can't imagine my life without it. I would hardly be a frontend dev if it weren't for CoffeeScript.
But the matter is that JS is going to evolve further, and CoffeeScript will get more and more out of sync with JS syntax and constructs. It will end up being a weird thing used only by those oldfags who started using it in ES3 era and were too stubborn to move on. It's already being considered an ill manner to use CoffeeScript both in open source and private projects. The JS world is becoming squeamish about CoffeeScript, and not unreasonably.
We do need a preprocessor that posesses all the CoffeeScript goodies (meaningful indentation, implicit return, optional parens and commas, ?
, ranges, etc) but at the same time embraces contemporary EcmaScript standard as much as possible:
nextscript compile foo.next --6to5
, and it will produce ES3 code.Thoughts?
@lolmaus it sounds like you're asking for "a better version of the ES6 draft that looks more like CS", is that what you want?
@sleepyfox, why would i want a different version of an EcmaScript draft? That's ridiculous, no runtime or transpiler would ever support it.
Because drafts leave draft status to become approved. And then runtimes (eventually) support them.
Are there two lists somewhere of the ES6 features, one of syntax changes (i.e. impact CS), one of object improvements that are already in CS as soon as they appear in JS?
Then looking at the first list, factor out those features that are not in CS? For example, modules but not default args or splats or classes?
It would give the conversation a more precise focus: what can't we do in CS running on top of ES6. Boy would I like that!
-- Owen
On Mon, Feb 9, 2015 at 3:21 AM, Sleepyfox notifications@github.com wrote:
Because drafts leave draft status to become approved. And then runtimes (eventually) support them.
— Reply to this email directly or view it on GitHub https://github.com/coffeescript-cookbook/coffeescript-cookbook.github.io/issues/128#issuecomment-73485885 .
@backspaces, no such list so far.
Here's what i know so far:
export default function() {
, without storing the exported feature in a variable.BTW, the CoffeeScript maintainer said that he might consider implementing modules but as an compiler to AMD/CJS rather than transpiler to ES6.
Again, this is totally off-topic. the cookbook is a reference for beginners of either obvious or verifiable best-ish solutions. The end result of this argument will be
really think this is a distraction for this project and would prefer the conversation moved elsewhere.
@michaelglass your probably right; but this does need to be discussed somewhere. Maybe a repo dedicated to this very issue?
I just ran into a CS incompatible issue: Tagged template strings
`hbs\`{{foo-bar}}\``
Does not work. It has to be in ES6 and there is a discussion about this issue.
@lolmaus You can write it like this without ;
and {}
. They are not always needed
for (let [key, value] of Object.entries(props))
style[key] = value
compare that to what coffeescript's for own key, value of props
will compile to, what do you prefer if you don't need to support older platforms?
var key, value,
hasProp = {}.hasOwnProperty;
for (key in props) {
if (!hasProp.call(props, key)) continue;
value = props[key];
style[key] = value;
}
FWIW, coffeescript 2.x generate ecmascript6 compatible javascript
ES6 is gaining a lot of spread. It introduces a lot of new concepts into JS. Here are nice overviews: short, comprehensive.
And people already use those features! Thanks to the effort from such projects as 6to5, es6-transpiler and Traceur, for a modern JS developer who does not use CoffeeScript, there is simply no reason not to use ES6 nowadays. Many modern JS projects are already being written in ES6. Moreover, popular JS frameworks already demand that their users code in ES6 out of the box (this includes Angular 2 and EmberJS).
CoffeeScript is essentially locked at ES5. Some ES6 features are accessible via backticks, but others directly conflict with the CS syntax, including said backticks. With main contributors having explicitly refused to support ES6, CS is doomed to become a thing of the past.
This worries me a lot. I still use CS for all my projects, but i will doubt using CS in a new project.
My problem is that i absolutely adore CS syntax. I worship it. After getting used to CS, i can't stand vanilla CS anymore.
Here's an extract from React sources i saw today (by the way, React is written in ES6):
This can be rewritten in CoffeeScript as:
JS code is more than 100% larger than CS with zero benefit!
Back to the matter. With CS maintainer having doomed CS to be obsolete, we need a replacement.
I suggest that here we: