Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Replace CoffeeScript with ES6 (thoughtbot.com)
351 points by Croaky on Jan 30, 2015 | hide | past | favorite | 168 comments


The reason that I like CoffeeScript is that it removes, what I consider, the unnecessary boilerplate of JavaScript and replaces it with a shorthand equivalent and good conventions. I feel that CoffeeScript is better at representing the intent of JS than JS. I can visually sift through CoffeeScript and understand the code much quicker than normal JavaScript, which in my opinion leads to more maintainable code. I'm not certain what is appealing about reading and writing more code for the same result.

Many people don't like that CS needs to be compiled. I don't see this as an issue since pretty much every application I work on these days is concatenated and uglified. So adding a JS compiler is already part of most JS application's build process. 6to5 is being compiled to ES5 anyway. Also, if you include in your build pipeline a source mapper, debugging is not a problem.


Ex-Coffeescript ,now Javascript with lot's of Python experience guy here.

The "I understand CS code much quicker" argument is a valid one theoretically, but In my opinion, it does not hold up practically that well.

CS got one thing wrong that Python got right: There are many ways to do things.

When writing CS, I understood MY CS just fine... but it always took me longer to understand the CS of other people. Sometimes even longer than JS. This is such a huge drawback, and even if there is coffeelint, for teams, this is deadly.

A lot of devs need to read a fair amount of foreign code. Even worse a lot of coffeescript writers also need to read and understand a lot of JS code.

Understanding and reading YOUR code slightly faster gets mitigated by having longer to understand foreign code.

While some JS purists fail to see that Coffeescript has some benefits, CS people also underestimate how "quickly" you can understand JS code, if you're experienced. It's all about what your brain is trained to do.

In my opinion, with ES6, I would argue for most people (ceteris paribus) it just makes sense to read and write JS exlusively, if you want to maximize output-productivity of a full, practical project.

Shaving off a couple of seconds "understand-time" of your personal, well written CS vs well written JS will just not compensate other things that will take you longer to do with CS.


As an example that I deal with daily, writing React components in CoffeeScript v.s. Javascript really highlights the elegance of CoffeeScript.

Of course you can reduce the JS verbosity with JSX instead... which again is introducing a pre-processor to the mix (one I personally am not a fan of, but w/e).

ES6 adds some sweet stuff for sure, but IMO it doesn't make JS a pleasure to work with yet (which seems to be the argument?).

I'm willing to bet it's not going to reduce the count in this list by much. https://github.com/jashkenas/coffeescript/wiki/list-of-langu...

I'm comfortable writing either as I'm sure many are, but when given the choice I opt for CoffeeScript.

P.S. Good luck telling someone using ClojureScript that they should switch back to Javascript.


"it doesn't make JS a pleasure to work with yet (which seems to be the argument?)"

My interpretation of what Retozi is saying is that CS just means that in addition to understanding JS, including ES6, you need to be familiar with all the different ways things can be done in CS.

I tend to agree, especially as JS is becoming an improving with each release.

What I'd like to see going forward is JS continuing to add selective sugar as is in CS, but also add functionality that makes going into a new fresh JS codebase and making sense of it easier. That side of things is less about CS, and more about the sorts of ideas you see in Dart and TypeScript.


My experience is the exact opposite. I find that CS removes a lot of the JS gotchas, and I'm not clear on the many ways that CS let's you do something, especially in comparison to JS. If anything it protects you a bit, by trying to enforce some of the "good parts".

http://arcturo.github.io/library/coffeescript/07_the_bad_par...

To each his own, but to me CS has been and continues to be a complete and obvious win over JS. 9 times out of 10 the benefit outweighs the annoyance of requiring a preprocessor for me.


On the multiple ways, I was sure I read a post that documented them all and had me nodding along but can't find it, this one seems good though [1].

[1] http://ceronman.com/2012/09/17/coffeescript-less-typing-bad-...


Out of all of those points, it's really just the commas and curlies that I've found can lead to some confusion, in my experience at least.

I haven't come up with a better approach than simply agreeing on a convention with your team though TBH. It's not too bad when everyone's on the same page and familiar with the gotchas (same could be said for most langs).

I put together a post comparing some of the syntax differences as it relates to building ReactJS components in case you're interested: http://rapin.com/blog/2015/02/03/reactjs-with-coffeescript/

Given that JS itself has quite a few different ways to do things though, it's kind of a wash.


> CS got one thing wrong that Python got right: There are many ways to do things.

I don't think this is necessarily true anymore, if it ever was. For hash-like datastructures in Python, please choose between object/dict/namedtuple/enum. In JS/CS all higher-level manipulations are dealt with through functions, whereas in Python depending on the situation you need factories, decorators, metaclasses and so on. And on a purely practical level people are moving away from the standard library (instead preferring arrow, requests, various unittest replacements etc.) but you'll still want to know the stdlib equivalents in case you encounter them in other code... and I can keep going like this.

I'm not saying this is necessarily a bad thing, sometimes one-size-fits-all just doesn't cut it, I just don't think Python can lay claim to being a simple language anymore.


> There are many ways to do things

Hopefully you realize that most Rubyists will strongly disagree and think that's not a "problem".


What's with the specious slam on Ruby out of nowhere?

Don't forget, Python is the community that brought us "There's Only One Way To Do It".


My biggest problem is definitely the source maps. It took me forever to get them to "work" and while the stack traces are mostly correct, they're often off by a line number or two. This makes debugging ridiculously hard when the line numbers are just "close".

I know this might not sound like a big deal in the grand scheme of things, but I also don't think CoffeeScript really improves on js all that much, so the annoyances of source maps are just not worth it to me personally.


Have you tried them at all recently? If a source map is off by a line, that's a bug that should be reported and fixed pronto.


I'm surprised. I use Browserify (and Coffeeify), which spits out a source map inline at the end of the file, which has not once given me problems.


That sort of thing completely killed any interest I would have had in CS. When it came about I already knew JS really well and the benefits of CS just seemed too minimal for learning a new language and dealing with bugs like that.


The things I hate most about CoffeeScript are the dash rockets and white-space significance. These are just opinions though. There are things I like about CS as well, like destructuring assignment and splats. Sometimes when I'm writing JS, I miss is, unless, etc... That said, I'd put my money on ES6 in the long run, though it doesn't really matter. People should use whatever makes them (and their team) happy and productive.


Significant indentation is a good thing. Haskell and Python do it too.

It's much easier to read indentation than it is to match up pairs of brackets in your head. In other languages, if the indentation doesn't match the brackets, you'll naturally read the indentation first and get the wrong impression of what the code does. In those languages, the indentation is supposed to match the brackets anyway. Why be redundant like that?


Significant indentation is enough for me to avoid Python. It just doesn't have enough to offer vs. the available alternatives without significant indentation.

It's much easier to read indentation than unindented/badly indented pairs of brackets, but you're setting up a strawman - it's not either or - and then you tear down the strawman yourself by pointing out we match the indentation anyway.

My code generally is properly indented and has start/end markers (though I mostly write Ruby, so rarely brackets), but what makes me stay away from significant indentation is that in the 30+ years I've been coding, I've never gone long without coming across situations where indentation has broken "in transit" e.g. with cut and paste between systems in annoying ways, or someone loading the code into an editor that butchers the indentation with tabs using "non-standard" tab settings.

When that happens, I'd rather "get the wrong impression" than have the code be broken.

That's one reason I want redundancy. My tools can trivially and automatically fix the result of breaking indentation when the indentation can be derived from the code.

Additionally, I want the visual redundancy, much like I find it far more comfortable to read syntax highlighted code even though it conveys no additional information.


I'm not setting up a straw man. I'm saying that it makes more sense if computers and humans are looking for the same things. Since humans read the indentation, computers should read the indentation too.

The way things are in bracketed languages, humans and computers read different things, and you just have to hope that they always match up. Sometimes they don't, and the human and computer will have a misunderstanding. To make it a real linguistic redundancy, like in Spanish, the compiler should read both and issue a warning if the indentation is incorrect or misleading. As it is, you and the computer are actually speaking different languages.


An easy solution to the tab problem is to use spaces instead. A good text editor will even let you use the tab key to insert a set number of spaces.


It's not just significant indentation. CS parses "f + g" differently from "f +g" (the former is an addition, the latter is a function call with "+g" as the first argument).


Yeah, the unary operators can cause gotchas.

Also, here's a gotcha I've run into where `a(b)` is considered different from `a (b)`

x a(b), c # => x(a(b), c);

x a (b), c # => x(a(b, c));


I like the indentation + braces redundancy because indentations are for humans, brackets are for the interpreter. Logic blocks are more explicit with brackets

I encountered a non-obvious Python bug that was caused by mixed spaces-and-tabs: to my human eyes, the indentation looked fine - the same as previous line, but the interpreter saw a different level of indentation.


> I encountered a non-obvious Python bug that was caused by mixed spaces-and-tabs

This is why PEP8 exists and people are supposed to follow it. Additionally, mixed spaces-and-tabs is a bug that causes poor readability - there's plenty of people who have their editors set to have tabstops as 2 or 3 spaces rather than 4, and your code will look wrong in their editors.

If you think there's any issues with mixed tabs and spaces in your codebase, Python provides a tool to find out - tabnanny. Additionally, any context-aware code editor will display a warning. (If you're using Sublime Text, the plugin to use is SublimeLinter - I assume there's similar tools for vim and emacs.) You can even set spaces and tabs to display differently in many editors!


Just installed SublimeLinter. Thanks!

It puts some icons in the margins, but I can't figure out how to get an explanation of those icons. I see a bunch of !s next to my import statements.


True, agreed. Python has the -tt flag but, UI mistake, it should have been on by default. Or at least -t.


Python's lambda semantics are limited due to the syntatic limitations created by Python's significant identation. That's not an universal problem of significant identation, but Python's syntax has it. I don't know, CS, so I don't know if it creates any such limitation.

Also, computers don't deal well with it. It's a smaller problem than people don't dealing well with it (the alternative), but it's still a problem. Anyway, this is much more relevant to scripts that run inside a browser.


> Python's lambda semantics are limited due to the syntatic limitations created by Python's significant identation.

(nitpick: you seem to consistently use "identation" in place of "indentation".)

I'm pretty sure that plenty of proposals consistent with Python's significant indentation have been proposed; python's lambda syntax is limited due to the BDFL not being convinced of the utility of more capable lambdas over using named functions enough to want to make Python's syntax more complicated to achieve it.

> Also, computers don't deal well with it.

Computers deal fine with it.


> nitpick: you seem to consistently use "identation" in place of "indentation".

Consequence of English not being my first language, and "indentation" being way too similar in it. I just can't spot the change.

I've seen a couple of proposals, yes they'd work, but they seem to be always ugly. But the problem is not that significant indentation makes it hard to create lambdas (Haskell's ones, for example are fine), but that it's hard to think about rules that won't create some kind of problem. On Python it's lambdas, on Haskell it's that they are often actually harder to write than explicit blocks (good thing Haskell has explicit blocks too).

And no, computers don't deal fine with it. To minimise some Python code you need almost an entire Python parser. Assembling Python code from small pieces (something that is really important for Javascript) is a frightening problem.


> And no, computers don't deal fine with it.

Sure they do.

> To minimise some Python code you need almost an entire Python parser.

I don't think source-to-source transformations requiring a parser for the source is an indication that it is problematic for computers to handle something. I mean, to execute the source code you need a parser, too, and no one says that needing a parser for execution is a sign that computers don't handle a language well.

> Assembling Python code from small pieces (something that is really important for Javascript) is a frightening problem.

Sure, assembling by cut-and-paste is a problem with significant indentation, especially when using media (like the web) which do not respect indentation well.

OTOH, using significant amount of cut-and-paste coding (rather than reuse by library code) is a sign of a problem with the language, development process, and/or execution environment, anyway, so I don't see it as a particular problem that a language structure isn't friendly to copy-paste coding.


I'm sure this has been argued to death but the counter argument is invisible formatting changing behavior is a bad thing. Sure if you get your entire team to use spaces or the same tabs great but passing open source code around to lots of programmers some of which use tabs and some of which use spaces ends up leading to wasted debugging time when someone used a tab where they should have used a space or visa versa.

On top of that I find it invaluable to be able to space out debugging code. Example

    void SomeFunc() {
       int x = doSomething1(1, 2, 3, 4);
       int y = doSomething1(4, 5, 6, 8);
       int z = doSomething1(5, 6, 7, 9);
       printf("xyz=%d,%d,%d", x, y, z);
       int a = doSomething1(0, 2, 3, 4);
       int b = doSomething1(1, 5, 6, 8);
       int c = doSomething1(2, 6, 7, 9);
       printf("abc=%d,%d,%d", a, b, c);
       int d = doSomething1(6, 2, 3, 4);
       int e = doSomething1(5, 5, 6, 8);
       int f = doSomething1(7, 6, 7, 9);
       printf("def=%d,%d,%d", d, e, f);
       return x * y * z + a * b * c + d * e * f;
    }
vs

    void SomeFunc() {
       int x = doSomething1(1, 2, 3, 4);
       int y = doSomething1(4, 5, 6, 8);
       int z = doSomething1(5, 6, 7, 9);
    printf("xyz=%d,%d,%d", x, y, z);
       int a = doSomething1(0, 2, 3, 4);
       int b = doSomething1(1, 5, 6, 8);
       int c = doSomething1(2, 6, 7, 9);
    printf("abc=%d,%d,%d", a, b, c);
       int d = doSomething1(6, 2, 3, 4);
       int e = doSomething1(5, 5, 6, 8);
       int f = doSomething1(7, 6, 7, 9);
    printf("def=%d,%d,%d", d, e, f);
       return x * y * z + a * b * c + d * e * f;
    }
On a long functions I find it much easier to see/find/delete the debug print lines by indenting them separate from the real logic but I can't do that on any language that enforces code blocks by indentation.

Commenting out also because an issue

    void SomeFunc(int v) {
       bool doit = v > 5;
       if (doit) 
       {
         DoSomething();
         DoSomethingElse();
         DoSomethingOther();
       }
    }
For testing I often want to comment out the if

    void SomeFunc(int v) {
       bool doit = v > 5;
       //if (doit) 
       {
         DoSomething();
         DoSomethingElse();
         DoSomethingOther();
       }
    }
If I was in python I can't do that

    def SomeFunc(v):
       doit = v > 5
       #if doit 
         DoSomething()
         DoSomethingElse()
         DoSomethingOther()
       
Error! I have to format the whole function just to comment out a line for testing. Yes in this case I could put `if true` (then requiring two changes instead of one) but there are plenty of other cases where code blocks by indent make it really annoying to work with my code.

So no, significant indentation is not a good thing.


Python 3 does not allow you to mix spaces and tabs. I don't know if Coffeescript is similarly strict.

I guess you've developed a habit where you're completely OK with having incorrect indentation a lot of the time, whereas I can't stand it. Just because it's easier to read for you doesn't make it easier for everyone, especially beginners.


I can't stand incorrect indentation either, but my experience is that it regularly happens anyway, and I'd rather not have that break my code.

And "incorrect indentation" has a very different meaning when the indentation is purely for presentation: As illustrated above, some people like to use the indentation to call out specific aspects of the code. That may be "incorrect" from Python perspective, but it is a way of visually providing additional information that is not available to you if you use a language that requires a specific indenting style.


I want to love whitespace significance, but after hitting refactoring pain points many times in Python, Coffeescript, and Sass/Less/Stylus, at this point I believe the brackets are worth their redundancy.


I love coffeescript, but it seems like the source maps are still pretty garbage. I often have to turn source maps off just to make Chrome's debugger not act so crazy. When I click to place a breakpoint in the original coffeescript code, it'll show up somewhere pages off from where it should go, and it just won't let me put breakpoints at certain lines.


I totally agree, but have you read the ES6 changes (i.e. what the article talks about)? To me, ES6 provides 90% of the good parts of CS, but without some of the tendency to let people write some of the headscratchers CS allows for.


If you've got any sort of programming skill your js will only be concatenated on test and production builds, not on development.

Your last paragraph makes little sense as you should never, ever be debugging a problem on live and I think minification has caused me a problem like twice in the 8 years since it's been popular. And it was pretty obvious when it did as the is wasn't even compiling.


> you should never, ever be debugging a problem on live

Until you have to


Then you've done it wrong. Very, very wrong. You should be able to replicate your live environment locally and not being able to is a sign of a very broken development process.

I just cannot emphasise this enough. One of my skills is debugging, everywhere I've worked I've been one of the top debuggers if not the top debugger.

Never, ever debug on live. If you can't recreate the problem locally, you don't understand the problem yet. Keep trying to replicate it until you do. I'm talking days of trying, not 10 bloody minutes.

The key to all debugging, the very fundamental skill, is consistent replication. If you can replicate a problem consistently, you can fix it.

There's a class of problems where this isn't necessarily true, especially for desktop apps, but web development problems and javascript, you can almost always replicate locally.


Sometimes your problem turns out to be a problem with production hardware or wiring, or depending on interaction with external partners who may not be able to replicate their interactions accurately for your dev/test environment, or otherwise impossible for you to replicate in dev/testing without already having figured out what the problem is.

While I agree with your overall sentiment, in any kind of remotely complex environment you sooner or later come across problems that you have no sensible way of reproducing in dev, and which will require you to debug on a production environment without it saying anything about the quality of your development process.


Bollocks, even in complex environments you should be able to test it outside. You can hook dev machines up to external partners, so there's absolutely no good reason to be using live environments for those problems.

I have seen production hardware or wiring be the problem once in my entire career. And I used to work for a company that ran and supported enterprise software on hundreds of different client-owned servers.

Most people these days will be running a few web servers at most.

EDIT: Worse still, we're talking about debugging javascript here, which makes what you're saying even more preposterous. Wiring, indeed.


> Never, ever debug on live. If you can't recreate the problem locally, you don't understand the problem yet.

I am guessing you have not been exposed to highly complex live environments. What you say is largely true but you state it as an absolute fact, which is a bit naive. Live environments tend to be far more complex than test or local environments and sometimes that complexity is what creates the bug. Sometimes the only solution is to debug live, but of course that is a last resort.


For 99% of programmers who aren't ever going to deal with the really tricky problems, it should be gospel.

I'm not naive, I did actually say "almost always" and "There's a class of problems where this isn't necessarily true", but perhaps you can't read?


> Then you've done it wrong. Very, very wrong. You should be able to replicate your live environment locally and not being able to is a sign of a very broken development process.

I feel this is statement is a tad hyperbolic.

One of my key skill sets is debugging, I'm pretty good at it. One of the things we can't do is completely replicate a production environment because we're a web hoster. Sure I can run and test stuff against our OS "gold images" but when you've added third party client code running on 300-400 sites on a single server that environment is not reproducible without a herculean effort. We also don't have the luxury of time to "Keep trying to replicate it until you do. I'm talking days of trying".

Four or five times a year I need to dig out ADPlus, point it at a customer's worker process and tell it to snapshot and dump when certain conditions/triggers occur. I then whip said dump over to my WinDbg+SOS environment to find out what the hell was happening in the process when it went bad.


I think there's a lot true in what you've written. However the root cause fix applied in a development environment is not always the fastest way to stop a user facing problem. Things get weird on live servers. I'm not suggesting altering code willy-nilly but a solid knowledge of production (logging, service status, etc) can lead to more effective debugging scenarios and faster time to resolution when things do go bad.


>If you've got any sort of programming skill your js will only be concatenated on test and production builds, not on development.

Development builds should use concatenated and minified .js code. That verifies that the development build performs exactly like the production build.

You can use source maps to help with debugging.


Folks, this was always part of the plan ;)

CoffeeScript is a fun little experiment in what's possible when you take JavaScript semantics and try to boil down the user interface to a minimalist surface. But JavaScript will always keep on rolling onwards — and to the extent that future versions of JavaScript take any minor inspiration or reference or overlap with things that CoffeeScript already does, the more the better.

For example, see this talk from four (!) years ago: https://www.youtube.com/watch?v=QTj6Q_zV1yg

There's more than one way to skin the JavaScript cat.

In other news, CoffeeScript 1.9.0 came out yesterday — with support for ES6 generator functions. A-la Python, in CoffeeScript, a generator is simply a function that "yield"s.


Thank you jashkenas-sama, please keep the good works with coffee (and underscore, backbone, etc.). We Rubyists and Pythonians are all (well, at least I am) eternally grateful to you for having delivered us from the evils of brackets, parenthesis, if !condition, and that thing were we had to firstArg = [].prototype.slice(arguments, 1) in every function where we needed splats.


^ To those not in the know, the above poster 'jashkenas' is Jeremy Ashkenas, the creator of CoffeeScript and Backbone.js


Only five years ago since the original announcement: https://news.ycombinator.com/item?id=1014080

> * CoffeeScript is an attempt to expose the good parts of JavaScript through syntax that favors expressions over statements, cuts down on punctuation noise, and provides pretty function literals.


I give credit to CoffeeScript with really helping to push the ES specs forward and think it helped introduce more people to JS and grow the ecosystem. Heck, I used it for a year, liked it, and had it change some of my approaches to writing JS.

That said, I hope it slowly fades into the background as more people go back to vanilla ES6 or go with something more powerful such as TypeScript (or Flux). With the progress around es6 and es7, gradual typing, macros, and other tooling around the language, I think CoffeeScript risks becoming a drag on getting people to learn modern JS and instead sticking with a language that has a lot of ambiguous constructions and fewer and fewer advantages over JS.


I sure hope you're wrong. The unnecessary clutter of plain JS is just painful to look at. I can't remember how many times I've looked over a 40 line block of JS searching for a missing. When there are many )} )}; } ; } ; } -- it is just downright frustrating to be be wasting any time on what is effectively irrelevant syntax. With CS, it's indent and be done with it. It's like SASS vs. SCSS. Or Haml vs. ERB. I can't, for the life of me figure out why anyone would prefer more to less. To take Haml as an example:

.my-div %h1 Some Text - some_ruby_code

vs the ERB of

<div class="my-div> <%h1> Some Text </h1> <% some_ruby_code %> </div>


> "With CS, it's indent and be done with it"

As others have said, it's all fun and games until two people edit the same source file, one of whom has the dangerously incorrect opinion that tabs are better than spaces :-)

I use a lot of semantic whitespace languages (CS, Haskell, Python), and it's a tradeoff: you gain in terms of redundancy, true, but there's an additional human overhead of making sure everyone's got their editors set up correctly. The larger the team, and a fortiori the number of teams, the bigger that overhead is. Smacking people about the head with PEP8 goes quite close to solving the problem in the Python world, but CS's Rubyish commitment to TIMTOWTDI militates against that.

"It's like SASS vs. SCSS. Or Haml vs. ERB. I can't, for the life of me figure out why anyone would prefer more to less."

Because HTML and CSS, despite their verbosity, are linguae francae. A CSS file is valid SCSS by definition - a less technical prototyper person can give you their code (perhaps even generated code from some wysiwig monstrosity) and you can refactor over it to remove redundancy, enforce conventions etc using the special SASS sauce. The SASS syntax does not.

A HTML file, likewise, is already an ERB file. HAML is 'backwards compatible' with ERB/plain HTML, so far as I recall, but mixing the two syntaxes is very, very ugly and a dreadful idea, and I'm not sure if it's possible to mix the two in similar template languages (Jade etc).

Point is: there is a human factor involved in picking shinier toys. I like HAML/Jade type templates, and Coffeescript for that matter, but I am far more comfortable using them on small teams or solo projects.


...two people edit the same source file, one of whom has the dangerously incorrect opinion that tabs are better than spaces

Commit hooks will help you:

http://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks

The bigger your team, the more you need them.


For open source projects, that's less of an option, but regardless, an individual's opinions about tabs and spaces are moot when working on a multi-dev project. You follow the project's conventions, or your changes don't get merged.


Yes it is frustrating that git doesn't automatically transfer hooks to cloned repos. I guess I understand the standard explanation of "git clone" never running arbitrary code on one's machine (although in a sense that is git's purpose), but it does reduce the use of client-side hooks in open projects.


I see no reason why anyone should care that CSS is valid SCSS and HTML is valid ERb.


Ditching all the useless lines of closing brackets and parenthesis is my favorite part of using coffeescript. Matching up brackets is a pain. The less I have to do that, the better.


My editors have had bracket/parenthesis matching for 30+ years, and automated indentation support as well. I don't get why anyone would do that manually.


Also if it works good, you can give them the same color as whitespace, which I always show, but with almost the same color as the background. This reduces the cognitive overhead a bit.


It's also possible folks will continue forking and improving CoffeeScript so that it keeps up with future releases of vanilla js (which is actually what I hope will continue to happen). Folks like me who come from a Ruby / Python background really don't like brackets and declaring variables, so things like Coffeescript, LiveScript, CoCo, etc. are wonderful tools even despite their occasional moments of weakness.

That being said, you're absolutely right, folks who write in Coffee should also absolutely eventually learn all the tips and tricks behind vanilla js also if they don't want to be bogged down.


I almost feel like the coffeescript variants are where the action is.


Care to list some? I'm always interested in seeing what's out there


The big one is probably LiveScript. I feel like it removes some of CoffeeScripts rough edges (the big one is the scoping rules; in LiveScript you have to use := to modify a variable in in outer scope).


Yes, but they slowed down...

The LS2 issues are from years ago and nothing is happening.


CoffeeScript syntax is better and cleaner than the ES6 syntax. It's a fun language, and I've been using it everyday since it came out. On small projects, it's top-notch.

But the future of CoffeeScript is bleak because many software designers are beginning to understand the value of type systems, e.g. TypeScript and Flow, for building maintainable Javascript code bases, and this means CoffeeScript is out of the picture for good because its long term design goal is to remain a minimalistic language, and doesn't intend to support these ideas. There have been attempts[0] to fork it to add a legitimate type system to it so it can scale, but they have faltered. Aside from that, the way CS deals with variable shadowing[1] makes it risky to use in large codebases.

So when ES6 syntax is tolerable and stable, I will pack my bags and move over to the ES6 land with great regret. I wish I could stay in CS land for longer, but you have to put away childish things eventually.

------------

[0] https://www.npmjs.com/package/typed-coffee-script

[1] http://stackoverflow.com/questions/15223430/why-is-coffeescr...


Variable shadowing sounds like a hacky way to solve problems caused by function scoping, which is solved in ES6 by introducing lexical scoping (i.e. the same scoping rules as in every other language).

It's also worth pointing out that CS and ES6 aren't really comparable technologies. ES6 isn't some newfangled preprocessor that simplifies syntax, it's an update to the standard which JS adheres to. CS is fundamentally limited because it compiles to ES5.1. When ES6 is implemented in browsers, CS will be able to do more.


>> which is solved in ES6 by introducing lexical scoping I thought JS has always had lexical scoping. What's new in ES6 allowing variables to have block scope.


Speaking of putting away childish things (like effect-ridden, imperative spaghetti code), PureScript is my new CoffeeScript.

http://purescript.org


Have you found a good framework that purescript supports in the vein of Angular or React? I had a look a while back but the support was a bit spotty for me.



I can't personally recommend any yet, as I'm still warming up to it, myself.

https://github.com/purescript/purescript/wiki/Recommended-Li...


I've been looking into that myself, but then I found Elm[0] and stopped looking. :)

-------------------

[0] elm-lang.org


Oh, Elm is cool. I get that. So is Haste[0].

But I think PureScript is a more practical choice for targeting JavaScript. (It generates much smaller, more readable output, for one thing.)

I don't promise to have my mind made up, though. I'm still furiously taking in all of this Haskelly stuff, and it looks like a pretty long road ahead.

I've been telling people that I feel like I've crawled into a tunnel, and can't back out again. I seem to have no choice but to keep crawling towards that tiny beam of light.

I don't know how many times I'd looked at the ML family, and just couldn't appreciate it immediately enough... but somehow I've managed to become completely obsessed, to the extent that anything less really turns my stomach.

[0] http://haste-lang.org/


  it solves a lot of the problems that CoffeeScript is trying to solve without drastic syntax changes.
I cannot speak to authorial intent, but for me the majority of the problems CoffeeScript(and moreso LiveScript) solves are syntax ones.


ES6 solves many of those same problems that required overly verbose or awkward ES5 syntax. Things like basic this-preserving closures, collection extraction, and so forth. Same problems, similar but less radical solution in ES6 vs. CS


Same, if I squint a little I'm just writing Python that runs in the browser.


ES6 has 'let', while CoffeeScript has an '=' that might be local binding and might be nonlocal assignment, depending on what's in scope. I wanted to like CS, but I don't want to live with that one decision.


The scoping issues with CoffeeScript is what triggered me creating this little language: http://batiste.info/CokeScript/ At this point it still a bit of a joke, but if I have more time to work on it I could take to a usable state.


Same here, after I learned about "lexical scoping" in college I couldn't imagine using a language without it.


Should be retitled 'Replace CoffeeScript with 6to5'.

You can start using transforms that provide features other than ES6: https://6to5.org/docs/usage/transformers/


Yes and no. Although we get some fantastic features, one of the most critical- the ability to neglect parens and curly braces- is lost in es6. I'm working on an es6 project right now and still prefer coffeescript.


That's interesting - personally I've always really disliked that about Coffeescript. It may just be because of how familair I am with C-family languages, but I always liked the default Javascript style far better.

So from my perspective ES6 is the best of both worlds - the better syntax of Javascript and the features that Coffeescript gave you.


For functions of single arguments, you parameter list parens are optional.

But it's not an objective fact that coffeescript's syntax is better. I prefer ES6. And even if you prefer coffeescript, it seems strange to claim that the most critical feature is purely aesthetic.


Assuming it's all ultimately JS, the aesthetic side is a big deal. It results in an easier time understanding and being able to debug the code, which is a huge, perhaps underestimated win.


It sounds like it would be relatively easy to write a preprocessor to do only this


Agreed that it's way nicer.


What CoffeeScript did was lodge the idea in people's heads that JavaScript can be treated as an assembly language to compile higher-level languages into. I'll bet many programmers' attitudes toward ES6 are: someone will write a compiler for my language, and I'll just use that.

It seems better to treat JavaScript as admittedly not being the most powerful language in the world, and to treat the standard as a kind of RFC that only compiler writers have to think about. For most programmers it works to just use CoffeeScript (or Lisp or anything) without worrying about standards, just as JavaScript programmers don't need to worry about how their processor works.


In fact, maybe Javascript is too powerfull. It would be interesting to get a stack machine emulation in the browser, with an standard set of libraries/tools for native access to the DOM and emulators for most interpreted languages out there.

Kind of a Java plugin that runs on web, instead of just tunneling through it.


There's also decaffeinate[1] that converts CoffeeScript to ES6.

1. https://github.com/eventualbuddha/decaffeinate


Why not both? This makes a good argument for ES6, but CoffeeScript's fundamental changes to syntax are just preferred by some.


Because one day ES6 will run in browsers without a build step.


In my experience all non-trivial frontend project I've worked on have ended up with some kind of build step (minification, linting, concating, ect), with or without a compile2JS language.

This isn't an issue for node projects as you can simply `require` the `coffee-script/register` module and node handles coffee scripts for you via normal `requires`.


You don't actually need a build step for either in development. Any client-side loader can compile your CS code on the fly.


I'm not sure that's a convincing argument – you will in almost every conceivable case have a build pipeline in place anyway, so there's not really a cost there.


I don't set up a "build pipeline" until I'm sure the app is going to deployed to a production environment. Why would I set up a build for what is essentially a fiddle, or if I'm just experimenting? The now-common workflow where people write build scripts at the start of a new project is just bizarre to me.


Sure, and why do people use C anyway? You can write binary directly without any kind of make utility.


Probably because machine code is not very human comprehensible.


Neither is minimized JavaScript


You're partially right, but every build step has a cost when you're working on a large project.


Yeah but then we'll just be compiling our ES8 code with 8to6.


Is that a major concern? In practice, it's unlikely any serious use of ES6 will run in a browser without a build step due to concatenation, minification etc


Some reasons why I will stick with CS:

* Optional braces and parenthesis. Results in visually cleaner and more compact code, especially when dealing with large objects.

* Requiring backticks to do string interpolation seems like an ugly hack.

* CS uses dots to slice and splice ranges:

    host?.split(".")[-1..][0] == "dns"
BTW, notice in the example above two additional CS features that don't exist in ES6:

* The existential operator `?` soaks up null/undefined references.

* `==` is compiled to `===`

* Expressions always return a value in CS, just like in Lisp, so no need to explicitly `return`

* Block strings and regular expressions.

And more: http://coffeescript.org/

Plus, CS just seems like it's always a step ahead of JS. In using it, you can code in a more intelligently designed language that enforces best-practices better than JS does. Doing so supports diversity, innovations (after all, many of these ES6 features are obviously inspired by CS).

Why abandon such a wonderful language when it still has so much to offer, and at the same time seems to be driving innovation in JavaScript itself?


I looked at 6to5 and started re-writing a few files of CoffeeScript in ES6. First impression was not great. I'd forgotten how many curly braces are required in JS. ES6's fat arrow is just not as nice as CoffeeScript's (required parentheses, no option for thin arrow). I'll no doubt try it out again soon, but I'm not a convert yet.


ES6 fat arrow syntax doesn't require parentheses if there is only one function parameter. If there are more, parentheses make the code more readable in my opinion.


'is' is also very cool: makes it harder to write '=' instead of '=='


> The existential operator `?` soaks up null/undefined references.

This seemingly minor feature is so huge for me. Accessing deep objects?.is?.a?.horrible?.pain?.sometimes?()


If you're accessing objects that deeply, something is breaking the Law of Demeter about locality of reference and looseness of coupling.

It's a syntactic convenience, but it leads to questionable patterns. Do you really want to silently collapse the hierarchy of whatever was null? I'd rather identify it and fail with a specific message or behavior rather than generically.


I wonder if CS will evolve further now that ES6 is about to land.


I wonder if ES6+ is going to become the new HTML5 - all these great features but no hope of proper browser support for years. I had no idea ES7 was also in development, so it seems like browsers are always going to be playing catchup. The comments on an article here the other day said people aren't upgrading tablets as often as phones. I can see a lot of tablets being stuck on ES5, that people don't want to upgrade, as they can still browse the Facebooks and Googles fine.


Firefox and IE11 already natively implement a majority of new ES6 features, and Chrome is getting there:

http://kangax.github.io/compat-table/es6/

The main laggard for now is Safari/WebKit.


Current stable browser versions:

FF 35: 60% Chrome 40: 35% Safari 8/Mobile: 22% IE11: 21%


Oops, yeah. I wrote "IE11" but I meant "IE TP".

The dev versions of IE/Firefox/Chrome/WebKit are up to 70%/69%/48%/28% respectively.


> Chrome is getting there

They are busy with that other programming language.


And the beauty of using ES6 is when the browsers you need to support handle, you just remove the transpiling step.


How much of this beauty will be fixed in ES6?

http://wtfjs.com


Some of those problems are with the DOM and browsers, not JavaScript.


True, there are numerous issues with each and every aspect of client-side web development: http://wtfhtmlcss.com


Bad code leads to inconsistent behavior. Who would have thought.


Most of the JavaScript community is already using this, thanks to tools like https://6to5.org/.

Developers are excited about new language features not because of browser support, but because it standardizes patterns they were already using (fat arrow functions, Promises, modules, classes, etc.) through CoffeeScript and third-party code.


I think your "most" is rather optimistic.

(6to5 didn't even exist six months ago.)


The "all or nothing" with CS has always been a non starter for me. I find it really hard to believe that it is possible for a team of more than 2 or 3 to remain happy with a choice to use it after any extended period of time. If you're out there though, I would love to hear from you!

And yes, this can be said for almost any tool choice, but my spidey sense tells me the half life for CS is about that of something like Jira.


I don't know what you consider an extended period of time, but I've been writing CoffeeScript full time for 2 years now, and it's been like that at my day job (moviepilot.com) for at least 2 more before I came. Couldn't be happier!

Team size varies between 8 to 15 people, roughly.


mobile.nytimes.com is written in CoffeeScript (frontend and backend) and is maintained by a team of around 8 people. AFAIK all of the developers are fine with it.


Is there a preprocessor/transpiler that lets you write vanilla ES6 but just without brackets, semi-colons, etc. like CoffeeScript?


Semicolons are already optional in JS. Automatic semi colon insertion (ASI) has a clear set of rules that are pretty easy to remember.

http://mattdesl.svbtle.com/to-semicolon-or-not


But ASI is controversial, because of the bugs that can be caused by it. (See "JavaScript, the Good Parts"). I make our devs (myself include) use semicolons with jshint, because I believe it's too easy to screw up.


After reading the linked [Isaacs](http://blog.izs.me/post/2353458699/an-open-letter-to-javascr...) post it made me realise a bit more about the language. I don't think I'd agree its easy to screw up. Its as easy as accidentally using global variables.


jshint warns about these bugs regardless of whether you have ASI flag turned on.

Writing semicolon-free code is easy. Just put a preceding semicolon before any lines beginning with: ( [ + -


Note that self = this is kind of a legacy hack for binding 'this'.

ES5 has Function.bind

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


It can also be nice when you're writing instance methods on a prototype. for instance:

    var Person = function(name) {
      var self = this;
      self.name = name
    };

    Person.prototype = new function() {
      var prototype = this;

      prototype.sayHello = function() {
        var self = this;
        return "Hello\n\n-- " + self.name;
      };
    };

    var me = new Person('Peter');
    console.log(me.sayHello());
Obviously that's a pretty contrived example but it illustrates the idea. It makes it really clear exactly what "this" means at different points in your code. As a bonus, if I had to reference the current context inside of a prototype method, "this" is now available.


I don't like `var self` at all and I find there are vanishingly few places where you can't just bind a function appropriately, but one important thing to note, if you do go down this route, is that `self` is an alias for the `window` object, so if you happen to miss out that `var self` assignment at some point, you may get unexpected results.

On that basis, if you must do this, I would suggest `var _this`, `var scope` (though that would probably be confusing if you had the misfortune to be using Angular), `var me` (unless you happen to find anthropomorphism distasteful) or... well, anything other than `var self`, really.


Interesting, I never knew that `self === window` – thanks for bringing that up. I'm not particularly attached to the name, just wanted to show an example where assigning `this` to some local variable is useful.


If you want to call something that increases performance by 50% a hack, feel free, but I'm going to use that hack until that's not the case.


Do you have a source? I don't understand how a closure over a single variable (this), instead of reassigning the value of the variable in a specific scope, would result in a 50% improvement in performance. Also -- the phrase "50% improvement in performance" itself is kind of dubious, no?


I wrote a simple benchmark, and `bind` seems to be mind-boggling slow.

http://jsperf.com/self-this-vs-bind


You can write your own or use lodash's for a dramatic speed increase. You can even stomp on Function.prototype.bind.


ES6 make JavaScript more powerful, but CoffeeScript is really elegant in a Python developer's scope.


I had fun with CoffeeScript but my projects definitely had its frustrations. CS allowed me to write some pretty damn ambiguous code.

Also when working with external libraries and dependencies, I found myself resorting to trial and error figuring out the correct syntax because nearly all documentation is written in JS and not CS.


Mmmm without drastic syntax changes?

Classes:

    There is no semicolon after the function name
    The function keyword is omitted
    There are no commas after each definition
Interpolation:

    `${1 + 1}` <- why not just # like everyone else?
Multi line strings:

     ` Now we have a 3rd
       string delimiter`
Fat arrow:

    $("button").on("click", () => { 
      // really? hanging parens? no function keyword?
    });
Destructuring:

    var [first, , last] = [1, 2, 3]
    // thats a var to assign vals inside an array
    // and just two commas touching to ignore a value

The whole post is about drastic syntax changes. The brackets are optional in coffeescript.

Besides coffeescript is just a tool.


> why not just # like everyone else?

You mean like CS? '#' actually isn't a very popular choice for this.

http://en.wikipedia.org/wiki/String_interpolation


Coffeescript's origin is in the Ruby community. The first interpreter was also written in Ruby. Ruby interpolates strings with #{} so that was a logical choice for Coffeescript.

The significant spaces thing was ironic given that Python is kind of the biggest competitor of Ruby (×) in the modern scripting languages space. Personally it's the main reason I'm not using CS (or Python or HAML or Slim), transpiling is number 2.

(×) kind of because Ruby is probably more successful in web development but less anywhere else.


I don't understand why significant indentation is a bad thing. It's easier to read indentation than it is to try and match brackets in your head.

The only times it bites me is when I accidentally mix spaces and tabs in the same block, which could use a warning.


I'm more into Ruby than in JavaScript even if I have 10 years of Ruby vs 20 of JS on my shoulders. In my experience Python is always easier to read than JS. It's easier than Ruby for the part that spares me from a silly looking sequence of end end end at the end of some nested block (but that : before a new indentation level looks silly too.)

The syntax of both Ruby and Python beat squarely any C-like language, even if Python looks strange to me. Perhaps is the mix of objects and functions that makes it look a little C-ish, or the many __name__ one has to write in same cases. Anyway...

I would do without JavaScript's {} () and ; or Ruby's end (which bugged me a lot 10 years ago) but unfortunately that easier syntax is offset by the too many times it came biting me with nasty bugs after I cut and pasted code around during refactoring. Or having to take really care of how many spaces I'm deleting to match the indentation level I must reach. The editor can't autoindent all the file for me. It's bad enough when I'm working in YAML files (the format of Rails's i18n db, another ironic choice) and I don't want to deal with it in all my codebase.

So in my experience significant indentation is evil because as a matter of fact is making me less productive. Lot's of people share the same feeling, lots of people are happy with that. No problem, there are so many choices that we can always pick what's best for us.

PS: I just thought that maybe an editor could autohide Ruby's end (or color it almost away) and still be able to autoindent code. Maybe I'll try to tell emacs to color end in dark blue (black background) and see what happens to code readability.


I don't like the class syntax in either ES6 or CoffeeScript.

In my opinion Ceylon nailed it:

    class Person(variable String firstName, variable String lastName) {

        shared String name => firstName + " " + lastName;
    
        assign name {
            value names = name.split().sequence();
            firstName = names[0] else "";
            lastName = names[1] else "";
        }
    }

Classes are effectively just closures with subtyping that export their shared members/functions.

Unrelated: A simple class like that shouldn't be mutable.


I'm surprised nobody has mentioned TypeScript. I've been using it in one of my projects recently (WebStorm even has a file watcher that works with very little set up on my Macbook).

TypeScript is pretty good at giving you a taste of ES6, it brings in a lot of features from ES6, such as the new classes, default arguments, generics, as well as a few of it's own features (interfaces, optional static type checking).

They ship it as a node module, so you can just "npm install -g typescript" and it's ready to go. As much as I dislike Microsoft, Typescript is something that seems to work well, and unlike Coffeescript, I can quite happily paste in standard Javascript code (even most ES6 code) and it won't break my source.


If you're going to use something with JS's syntax, at least take Typescript or Flow for some compile time checks (optional types, function arity, variable names, &c).


Is there anything like flow for Coffeescript?


Braces combined w/ something like clang-format or gofmt are clearly better. Perhaps a really advanced editor (that most people don't use) could offer a similar experience for braceless (sig. indent) languages.

Short braceless code typesets beautifully, but you can probably get a similar effect w/ an appropriate 'braces highlight at lower contrast when autoindented as expected'.


The body of the post doesn't support the title's recommendation. Each section shows how ES6 either has an equivalent feature to CoffeeScript, or almost does; in other words, it is approaching feature parity.

To replace one tool with another, you need a compelling reason...and "it's almost at feature parity" is not that.


First time I heard of sprockets (weird, being German). How many JS build tools are there out now? And is none of it deprecated/abandoned?

Other than that, the braces/indentation issue alone will keep people with CS. Can its compiler emit ES6, by the way?


Sprockets is part of the Rails asset pipeline - it's not used much outside of the Rails world.


Minimizing javascript code using a minimizer currently cannot be done well in a guaranteed way, because the minimizer must make too many assumptions. Therefore, I think javascript is too dynamic for a web-language.

Unfortunately, they didn't solve this with ES6.


For those using browserify, you can use es6ify to compile ES6 to ES5 on the fly.

https://github.com/thlorenz/es6ify


Alternatively there's 6to5ify[1]

1. https://github.com/6to5/6to5ify


The biggest reason why I still dont use coffeescript is that most compile javascript tooling doesnt work. I cant use types from TypeScript, or use JSX extentions with coffeescript.


You can use coffee-script with JSX. I'm using cjsx-loader with webpack, and there's also a stand-alone cjsx compiler.

https://github.com/jsdf/coffee-react

https://github.com/KyleAMathews/cjsx-loader


CoffeeScript compiles down to ES3, which means it's compatible with Old IE. The ES6 compilers can only compile down to ES5.


That's not necessarily true. Many of the features can be made ES3 compatible. Of course knowing which ones are exactly isn't always straightforward.


Coffeescript is pretty damn ugly. For god sakes can people please use parenthesis when calling functions with arguments?


I do it in my coffeescript for function calls. You just need some guidelines and some discipline.


Why add unnecessary clutter?


It is not unnecessary, it helps the reader building a mental model about what is a function and what is not. I would concede It can be useful to create some DSL or to access an object lazily but the is a price to pay: a more opaque code base


Lisp programmers would love to disagree


Parenthesis are not unnecessary in Lisp they're an essential delimiter in defining an s-expression's structure (does not need to be parenthesis but some token is required).

But for me that one bit of syntax is a lot less that the multitude required for many languages.

For something even more syntactically minimal there is Forth.


There is very few features of ES6 that are not syntax sugar.

Those features will be (or already are) ported to CoffeeScript.

And the CoffeeScript sugar is just tastier.

ES6 syntax is kind of CoffeeScript for people who hate meaningful indentination and it's quite decent for that purpose.


> There is very few features of ES6 that are not syntax sugar.

(Weak)Map, (Weak)Set, Symbol, Generators, Promises, Modules, Proxies... these aren't sugar.


So generator, weak references and proxies.

Promises, modules we already had. Native implementation doesn't provide new functionality, just picks winners.

I'm really excited by generators and proxies but those are available in latest version of CoffeeScript already.


Good




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: