Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
A CoffeeScript Intervention (pragprog.com)
107 points by telemachos on May 4, 2011 | hide | past | favorite | 36 comments


I don't quite agree with the conclusion of the article ("you’ll come away with a better understanding of JavaScript"). The fact that CoffeeScript hides scoping and other stuff from you means you will never have to learn how JavaScript really works.

You can argue whether this is good or bad, but it's not giving people a better understanding of anything, it's just making them follow best practices unknowingly.


(I'm the author.)

JavaScript can be pretty overwhelming to newcomers. You mention scope, which is a good example of where CoffeeScript actually clarifies rather than hides the underlying semantics.

The most important thing to understand about scope in JS is that only functions create scope. This is very different from C and Java, and since JavaScript looks like C and Java, that difference is surprising (see e.g. http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-...). When you learn the same rule in CoffeeScript, it feels a lot simpler. And that understanding can carry over to JS.

Granted, the compiler is generating the `var` keyword for you, but the mapping is trivial. What's important is that scoped variables have the same behavior in both languages.


This is tangential to the main thread, but the weirdness that is hoisting surely confuses a lot of people. (To clarify: hoisting seems to me to be more or worse than just "there's no block scoping.") Just now on my the subway ride home I came across this example from David Flanagan's JavaScript: The Definitive Guide:

    var scope = "global";
    function f() {
        console.log(scope); // Prints "undefined", not "global"
        var scope = "local"; // Variable initialized here, but defined everywhere
        console.log(scope); // Prints "local"
    }
I'm someone who uses Javascript only occasionally, and I'm trying to learn it better. But I thought I understood scope just fine: no block scope, function scope, lexical scoping within functions and nested functions. I may have read about "hoisting" before, but honestly it never sunk in until today.

So I'm assuming that Coffeescript always compiles down to Javascript where variables are explicitly hoisted upwards in declaration? (Answer appears to be yes from a few quick tests here...)


I don't see how adding a completely different syntax layer and compilation makes coding in JavaScript less overwhelming.

Using jslint eliminates item 1.

Item 2 is a stupid language quirk. Guess what, Coffeescript is a whole new layer of quirks.

Aside from item 4, the rest are based on a mistaken idea that reducing typing somehow is a huge advantage. (I don't know, it may be for some people but I'm either too fast a typist or too dumb a programmer.)

CoffeeScript is probably very appealing to some people because it imports coding conventions from some other language (Ruby I guess) that they like. I happen to like JavaScript and running code through jslint once in a while is a heckuva lot less annoying than having to compile code and deal with debugging "assembler".


Nice article Trevor. But you could have avoided the last statement creating unnecessary FUD in the minds of Rails users.


Ha, yeah, but I did want to mention the Rails 3.1 support somewhere (a vote of confidence in CoffeeScript from the highly respected Rails team); given that, a link to http://doihavetousecoffeescriptinrails.com/ seemed the best way. Rails people have a good sense of humor. I hope...


All I'm thinking is that people should start using JSLint instead of making up languages on top of JS. That will catch most of the bugs due to common misunderstandings of the language.


JSLint can't solve the "I forgot to include a frickin' explicit return again" problem, can it?


It also can't solve the "`function () { return … }` is syntactically very heavy" problem.


At JSConf yesterday, Brenden Eich (creator of Javascript) specifically said he thought CoffeeScript's syntax was fantastic. He also stood on stage with the CoffeeScript author while he talked about ways to get errors in CS to return line numbers in CS source, rather than JS.


That's a first world problem of ruby devs I think. When you're used to it, you never forget to write return statements.


Ruby is far from the only language that is commonly used without explicit return statements (and it at least has them). It's just currently the most popular one.


Agreed. I hardly think that people who haven't used languages like Ruby or Coffeescript (with implicitly returning the last expression) ever forget return statements in a way where everything would be okay if they just added a "return" keyword. When I use Ruby and Coffeescript, I consciously have to think "no, I _shouldn't_ write return this time"; I find it hard to believe that, without using a language like this, anyone would just write an expression and expect it to be returned. I could see an argument that if you're returning the application of a function, but it has always seemed extremely natural to me that I think about what I'm returning when I write a function; I actually always have a little bit of trouble adjusting to writing Ruby-style return-less code.


it depends on how you think of functions... If you think of everything as an expression, of course it has some kind of value.

That being said I prefer not to have to write "return" but work plenty with languages outside of ruby and have no issues writing return when necessary.


> it depends on how you think of functions... If you think of everything as an expression, of course it has some kind of value.

Sure, and functions by definition return a value. I know programming isn't math, but the notion of a "void function" is somewhat of an oxymoron.


Ruby, Lisp, Smalltalk, Python, Forth, Perl... Nearly anything that's not a descendant of C or Basic lets you write in terms of expressions.


This is why I think 'let' pretty much fixes (or maybe sanitizes) scoping in JavaScript (see e.g. https://developer.mozilla.org/en/New_in_JavaScript_1.7#Block...). In summary, it allows you to define variables per block.

Unfortunately, it's a feature only available in Mozilla's JS engine at the moment.


Wow, this article actually had the opposite of its intended effect with me. I had always expected that CoffeeScript was a better form of JS that I should probably get around to learning. Now I've just learned that besides having an unpleasant syntax, it actually redefines some important features of javascript to behave in novel ways.

As an example, the whole point of setTimeout is to be able to do the sort of thing shown in Example 4. Defeating it just means you now have to search for another way to do the things that setTimeout was designed for.

Same with variable scope. If you can't declare a global without actually standing in the global scope, that makes things harder, not easier.

Beyond that, I glazed over at seeing various little ascii arrows. I'm sure they're there for a reason, but by then I was already halfway out the door.


First, use or don’t use what you want. If you don’t like the cleaner CS syntax, stick to writing raw JS. Your other points aren’t especially valid though:

1) You can trivially use setTimeout just as you did before. CoffeeScript just gives you a couple extra tools for simplifying things when you have use cases like the one presented in the article.

2) As for the global namespace: if you want to attach something to the window object it’s much more readable to just write "window.foo = bar" or whatever. In general though, I defy you to come up with an example where you want to define global variables from some other scope where your code wouldn’t end up just as clear but more robust with cross-scope variables defined in some high-level scope. Pretty much everyone agrees that JavaScript’s "pollute the global namespace by default" feature was a mistake.

The ascii arrows are by far the best part. JavaScript turns out to be a very nice language (semantically) for writing functional-style code. Unfortunately, the regular JavaScript syntax makes defining functions so unpleasant that I go out of my way to avoid extra ones. CoffeeScript makes defining functions so easy that I go looking for ways to use more, instead.


If you can't be bothered to learn the behavior of keywords as fundamental to JavaScript as "var" and "this," then yes, you'd better be using some wrapper. Items (3) and (5) seem to be the only valuable features demonstrated here, and (5) should be present in the ES Harmony (it is already present in JS 1.7).

The article states that

> It’s about more agile code

but I find this claim dubious when the best JS tools are for JS, and not CoffeeScript. I believe that the features provided by the Closure compiler are more beneficial for stable JavaScript development (annotations, etc), and carry a significant performance incentive.


Without agreeing or disagreeing with your conclusion, I'm not sure I understand what you're reaching for with the opening sentence: If you can't be bothered to learn the behavior of keywords as fundamental to JavaScript as "var" and "this," then yes, you'd better be using some wrapper.

That seems to be trivially true, but in context it only makes sense if you're implying a bi-conditional, namely that the only reason to use a wrapper is if you don't understand var and this.

I believe that to be false. There are many reasons to use syntactic or semantic sugar even when you understand the underlying language very well. As a demonstration of this, I give you that most tools of this type are written by people who understand the underlying languages incredibly well and design such tools for their own use as relative expert users.


Oh, I just meant that those (confusion with `this` and `var`) were pretty silly things to point to in praise of CoffeeScript, as they are so easy to understand and fundamental to JavaScript. Like you said, CoffeeScript is aimed at a broader audience than those who can't grasp JS basics.


The problem is not confusion about them, or inability to figure them out, per se. Dealing with syntactic awkwardness and features full of tricky corner cases takes mental effort even if you can understand them perfectly. Coffeescript let you (to a greater extend than JavaScript) write and read just the code you mean, without having to think explicitly about these questions every time. You still have to understand JavaScript in a fairly deep way to build solid CoffeeScript programs.


I for one am quite dubious when it comes to the idea of people learning Coffeescript "instead" of Javascript. I don't think you should pick up CS until you have at least a moderate understanding of JS.

Also, I don't think CS is a tool to abstract away these problems from DEVELOPERS...that is, it's not so developers don't have to understand these issues...it's a tool to abstract away these problems from your CODE...so that you don't have to write all sorts of repetitive, dense, and gnarly code to work around all this stuff

. A lot of times when Coffeescript comes up, people think that it's purely for people that don't "understand" Javascript, but this is not the case at all. I know some supremely knowledgeable Javascript developers who have adopted it.

Tooling is, imho, one of the biggest drawbacks of Coffeescript at this point; however it's making progress. Coffeescript produces fairly clean and readable code (though it is very verbose), and it also has pass-through syntax for both code and comments...so tools like Closure Compiler could be used on the generated Javascript without a whole lot of trouble.

Some tools can be adapted by the user to use CS, and in other cases the creators are working to support Coffeescript (there are some at Mozilla who want to add debugging, etc support for CS). In cases where all else here fails, the community is working on providing Coffeescript versions.

Some people may not want to use it, or may be unable to due to some tool or workflow not being supported; but I've found most JS devs I know able to pick it up and use it quite easily with good returns.


I don't think the point is "you won't need to learn how these work!"; rather, it's "you don't need to worry about using the normal convoluted ways of dealing with these". It's never claimed that => implies (ha, logic humor) that you don't need to know how this works, just that => helps you deal with a common annoyance found with using this.


My main point is that only those who cannot be bothered to learn the language's finer points (I don't consider these to be amongst them, but as indicated by this blog post, others do) will reap significant benefits from using a tool such as CoffeeScript. Anybody else would be sacrificing too many useful JavaScript-specific tools to justify the benefits of a slightly more expressive language.


> Anybody else would be sacrificing too many useful Javascript-specific tools...

What exactly do you mean by this? What is there that you can do in Javascript that you can't do in Coffeescript?


> the language's finer points

I wouldn't call those "finer" points.


You don't read parentheses.


Very much agree. I fully understand the scoping of "this" but that doesn't stop me from hating life every time I have to write "var self=this;".

In other languages I can put up with a reasonable amount of pain but "this" and dealing with loops in JS puts me over the edge.


This and the recent release of 1.1.0 gave me a push and I spent some time converting a small library I maintain (http://flickrshow.com) to CoffeesScript as an exercise and and education into the syntax and potential benefits.

As it was a 1-1 conversion it was fun to see not only how much syntactical cruft the CS syntax removes but also how a few sloppy lines got tidied up, (mainly existence checks). In that sense, it adds value. It'll be interesting to follow this up with how easy it is to churn out new code ...


It looks like the future of JS resembles CoffeeScript quite a bit: http://brendaneich.com/2011/05/my-jsconf-us-presentation/


Interesting. I didn't know about the 'do' keyword or the repetition bit with {x,y} returning {x: x, y: y}. Pretty cool!


The {x,y} rvalue syntax isn't in the CoffeeScript documentation. This is the first place I've seen it.


It was but it got dropped in the doc update for 0.4 or thereabouts. I was hoping he'd take it out for a while because it complicates the disambiguation of braceless object literals but it seems most people like it, so meh.


It's a bit weird that it breaks alpha equivalence (i.e. you expect your program's semantics to be invariant under local variable renaming) but I can see why people like it. It's certainly compact and idiomatic, and there's a nice (albeit superficial) symmetry with destructuring assignment.




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

Search: