Hacker News new | past | comments | ask | show | jobs | submit login
This is CoffeeScript (thoughtbot.com)
184 points by franze on Aug 22, 2011 | hide | past | favorite | 89 comments



I am a recent coffeescript convert. When I first heard about coffeescript I dismissed it offhand as a pointless abstraction over javascript, which I judged to already be a high level language. (In retrospect, I am ashamed to say it, but I think that I found the syntax to be intimidating.) I then went on to continue, happily, writing thousands of lines of javascript.

Somewhere along the way, I came across Paul Grahams essay "Succinctness is Power" ( http://www.paulgraham.com/power.html ), and I thought about how my productivity could be increased if I had access to a language that offered me the ability to do more with less. That was when I decided to revisit Coffeescript.

For my first task, I decided to rewrite some of my simpler javascript code into Coffeescript just to get a feel for it. Initially, the things that had initially repulsed me were somewhat irritating:

* The lack of parenthesis and brackets - I doubted that it would be possible to maintain code readability without them

* The reliance on indentation

* The overall "strangeness" of the appearance of coffeescript code (to someone with a predominantly java background)

Here's the thing though. All of those objections are only surface deep. Once I actually started to code in Coffeescript, I found that I became completely comfortable with the syntax. As a matter of fact, I don't think that I could ever go back to conventional javascript again. Especially because I would lose (among other things):

* An elegant syntax for writing classes using javascript

* List comprehensions

* Elegant string interpolation (it's the little things that count)

It is easy to be skeptical about coffeescript if you natural lean away from things that are surrounded by hype, but, take it from me, coffeescript really is an extremely valuable tool that no web developer should be without. It is more than just a way to write pretty javascript. It is a powerful, flexible, and elegant language in its own right. Don't be turned off by its syntax, give it a try today!


"Just like JavaScript but nicer to type." was a decent pitch to make CoffeeScript sound safe. But it's become so much more. And you get past the simplicity of that pitch quickly if you use CoffeeScript earnestly.

Going through the Table of Contents on http://jashkenas.github.com/coffee-script/ I've picked out the features of CoffeeScript that make it a different beast than just a JavaScript without warts.

* Lexical Scoping and Variable Safety * Conditional Assignment * Splats * Comprehensions * Everything is an Expression (&implicit return) * The Existential Operator * Classes, Inheritance, and Super * Destructuring Assignment * Function binding * Chained Comparisons * Extended Regular Expressions

This is beyond a simple sweetener for your JavaScript code. Yes, you could write your JavaScript like you write your CoffeeScript, but you wouldn't.

Try this little jewel in Try CoffeeScript and you'll see what I mean:

[open, contents..., end] = "<impossible>".split "" alert contents.join ""


I think the jury is still out on whether or not the existential operator is too clever for its own good (in particular when used as part of a chained expression).


What is so clever about a nil object check?

I suppose if you're using it to make skirting the "Law of Demeter" and thats something you don't want to do it could seem like something bad.

But I'll take "foo?.bar()" over "foo.bar() if foo" gladly.


The issue is in an expression like "out = foo?.bar()". What I want is to only assign to out if foo exists, but the compiler has no way of knowing that-- it'll evaluate to undefined instead. In this situation I need to use "out = foo.bar() if foo".

That's easy enough to remember, though.


Yeah, I can see the argument in favor of it. Easy to miss when reading through code, but arguably unlikely to be used on a way where it would really matter if you missed it while scanning.

I found myself trying to decide whether or not to use it the other day and decided for now it was too clever. So I guess the jury is out in my own head, maybe not in anyone else's.


I find it quite useful in Io, including chained expressions.


I don't subscribe to the notion that you can write code faster with less keystrokes (vi/emacs, anyone?). I do however, understand that a cleaner syntax would lend some readability and simplicity to your code once you learn said syntax. Ultimately, I find that the problems that CoffeeScript solves, and solves quite well, are not really that big of a deal for me given that I've been working with Javascript enough to get used to the quirks. I'm not sure if I'll ever use it myself, but I can't blame anyone who would; this article does a good job explaining some of the benefits.


"Ultimately, I find that the problems that CoffeeScript solves, and solves quite well, are not really that big of a deal for me given that I've been working with Javascript enough to get used to the quirks."

I wouldn't expect you to believe me until you've used CoffeeScript for a little while, but I think you're definitely wrong about this. CoffeeScript simply has better syntax than plain js in every way, and any js developer will be more productive using it. The only drawbacks are dealing with file conversions and debugging, but these are something like a 10% penalty at worst on top of a 100%+ productivity boost. It's not just an aesthetic preference thing. CoffeeScript is a much better language and is pretty much guaranteed to save you time and mental effort.


> CoffeeScript simply has better syntax than plain js in every way, and any js developer will be more productive using it.

That's a pretty bold claim. Have any examples to back it up? Most of what I've seen of coffescript (note: I haven't looked hard) seems to be relatively similar syntax with fewer characters or fixing JS gotchas that many developers are familiar with.

Both of these are useful things, but they don't make a 100%+ productivity boost in my mind.


List comprehensions. Distinct 'of' (property) and 'in' (value) operators. Bind a function to current 'this' with =>. Nothing winds up in global scope unless you mean it. Use reserved words as property names. Existential operator and assignment. Always use '==='. Everything is an expression:

    value = switch value
        when 1 then one
        else whatever
Closures.

  do (value) ->
     #value is wrapped in a closure
The 'class' macro.

And that's just off the top of my head. Yes, it compiles to JavaScript. You could write all this by hand. It would be a waste of your time-- CS writes safe, efficient, readable code faster and better than you do, every time.

Look harder.


Peoples' obsession with CS having the class macro is weird to me. Seems like laziness more than anything - once I grokked JS's protoype object model I've found it to be ridiculously powerful AND I got to learn a cool new programming abstraction at the same time. All the rails guys I know are going gaga over CS but I just don't see the point as I like and can be efficient in JS.


I can't speak for anyone else, but I treat the class macro as pure shorthand. I understand implicitly that "properties" in a "class" are being assigned one at a time on the constrictor's prototype, and frequently use that knowledge for metaprogramming. You call it laziness; I call it nicer syntax.

I understand that puts me in a small boat. In my opinion, people shouldn't use the class macro without knowing what it really does. Actually I'd extend that to say people shouldn't use CoffeeScript at all without an understanding of the JavaScript it compiles to, just as you shouldn't use C without an understanding of the assembly it compiles to... But that's probably wishful thinking. It wouldn't be an improvement for those people to write assembly (or raw JS) instead.


I don't particularly like all of the syntax choices in CoffeeScript, and I absolutely don't subscribe to the theory that fewer keystrokes means cleaner code, but on anything complex I think CoffeeScript is a better choice than vanilla JavaScript.

It really is true that having a compiler make it impossible to screw up your scope saves you from a lot of mistakes. This feature is probably the thing I wish we had put in Objective-J most. It's also really nice to have a syntax for classes.


Sounds like a bit of a straw man to me. It'd depend on just how big the difference in the number of keystrokes there are, would it not?

Do you not agree that writing 100 lines of code instead of 1000 lines saves time, when writing it but perhaps most importantly when reading it and developing it further?

I'm not saying CoffeeScript cuts down the number of lines of code by a factor of ten, but, depending on what you do with it, often by 50% or more.

Making it about "keystrokes" is a bit disingenuous, it's about cruft (aka "keystrokes") but it's also about lines of code, imho.


I'm less concerned about raw keystrokes than I am about repetitive things that I have to keep in my head at all times.

Simple iteration over the key/value pairs of a javascript object requires that I remember to check hasOwnProperty at the right times. Soaking up nulls is a pain. Dealing with args kind of sucks. There's quite a bit more.

It's less valuable that these things can be done with shorter character sequences, and more valuable that I don't have to think about them nearly as much.


The problem with Javascript is that because of political reasons it has only evolved slightly in the last 12 years, so it takes a lot of effort to avoid the bad parts.

I about CoffeeScript as JSLint + Syntactic Sugar. Both of which mean you need less heroics to get Javascript right.


I agree with this. As a counter example I can completely understand why some people use GWT because it provides a development infrastructure and code enforcement that you just can't get from normal javascript coding. I can't say that CoffeeScript provides enough of a change in discipline over normal javascript coding.


Also, HNers may find my open source book on CoffeeScript useful: The Little Book on CoffeeScript http://arcturo.github.com/library/coffeescript/


Am I the only one who thinks this is horribly difficult to visually scan?

    item = new Item title: "Awesome", id: 2
Less isn't always better. I like the parens, at least if there's more than one argument.

    item = new Item(title: "Awesome", id: 2)
It's much easier for me to glance at this and know what's going on.



Love CoffeeScript, but yeah omitting parens makes it hard to read in this case. I follow Visual Basic convention. Use parentheses when using the return value. In this case, the constructor function returns an object. Omit parentheses otherwise, i.e. using a function as a method (no return value).


All I can say is you get used to it, and it encourages you to write in shorter sentences, which results in more readable code overall.


What else would it mean?


I can understand what it means, it just takes slightly longer to comprehend without the parens providing a visual cue that it's a function call.

It only gets worse with nested function calls:

    item = new Item title: new Title "Awesome", id: 2
The syntax isn't ambiguous, but that doesn't mean it's easy for humans to parse.


In a language where there are two drastically differing ways to express the same idea, it could mean anything.


How are we having this conversation in English, then?


Well, it took about 8-12 years of practice for me to be able to do it correctly, and at least twice that to achieve my current proficiency. So when I have my choice of designed languages, I'd like one that tries to learn from the failings of the organic ones.


It could easily mean that item is a 2-tuple.

item = (new Item title: "Awesome", id: 2)


When I first checked out coffeescript, I had a feeling that Jeremy was unfairly trying to show it off as cool by being less verbose than javascript - a feeling I found echoed in one of the tweets by Zed. But after actually using it, I realized that I had missed the whole point.

Coffeescript has that ruby-esque intuitiveness. A lot of time I refactor code on a gut feeling that it'll work, coffee -p, yup it does ... 9 out of 10 times. closure, is, in, of, soaking null references lets you focus more on your code rather than on patterns, handling corner cases and avoiding mistakes; and I just discovered the fat arrow thanks to this post. (Yup, the documentation is all there on the homepage but, agree or not, learning is incremental and involves mistakes and serendipity.)


Dug up Zed's tweet: https://twitter.com/#!/zedshaw/status/101746443949322240

... which does indeed miss the point -- the side-by-side comparison on the homepage is not to show you what the equivalent handwritten JavaScript would be -- it's the actual JS output compiled from the CoffeeScript on the left. More of a "nothing up my sleeves" and no bullshit maneuver.

In a perfect world, CoffeeScript would compile into the JavaScript you would have written in the first place -- but that's quite a tall order.


If you're doing a side-by-side comparison, then you want to compare with what a human would write, not with what a compiler would write. Otherwise, you're not really showing the advantages of your language, you're showing how easy it is to read the object code -- something that's only really an advantage when debugging your compiler and/or trying to map the generated output back to the source for debugging purposes.

I mean, look at what Hello World in C is, compared to Hello World in Haskell!

http://pastebin.com/sePpUJ1J (Haskell source)

http://pastebin.com/seqAy4VD (C, generated from the Haskell above)

Clearly C is unreadable garbage! (It's less expressive than Haskell, for sure, but showing generated output makes it look far worse)


"What a human would write" isn't the purpose of the comparison. "This gets put in, this comes out" is. Did you not read the heading on the overview page? It doesn't even say "comparison" anywhere. The second paragraph talks at length about how CS compiles to readable Javascript. Then the examples show you that readable Javascript. You're missing the point.


Why do I care if the output javascript is readable? It's object code. I don't want to care about it.


Unlike environments like GWT or ClojureScript, coffeescript doesn't treat the JavaScript as an invisible target language. You do actually think a little about the JavaScript that your code is being compiled into (or maybe more accurately, translated into).

This makes CoffeeScript fit really well into the JS-centric environment that has grown up around tools like JQuery and backbone. It's also very easy to debug in the browser compared to the environments that are targeting JS as an object code.

Personally, I don't think of CoffeeScript as a fully independent language but, rather, as a way to write JS which is cleaner, more reliable, and more fun.

If you really want to turn JS into a black box (and there are some good arguments for that), GWT or ClojureScript might be better choices for you.

(I've been writing a bunch of CoffeeScript lately and loving it. I'm very anxious to try my hand at ClojureScript also. GWT has always seemed very unwieldy to me.)


You'd only care if you ever needed to interactively debug your app in the browser. So, unless you're a fan of old-school debugging (ie not debugging, just writing out to the console) you do care about how the javascript looks.


I don't think he is- I think he's saying that the point being made is the wrong one. It should be a comparison of the two languages because that's what people would want and expect.


Especially since if I had to write that JavaScript by hand, I wouldn't.


Sadly, to write good JavaScript, you somewhat need to do that. Of course, you'd use more functions instead of repeating the same patterns over and over.. but there're things you just can't factor out and this is, in my opinion of course, exactly where CoffeeScript shines.


<public_display_of_affection>

Dear sir,

I'm jumping on my bed right now out of ecstasy, for my unworthy comment has garnered a reception, from a noble soul like yours.

You just made by day. In fact, you do it through the means of coffeescript everyday. Thank you for coffeescript, kind sir.

Hats off.

A broke, insecure, forever alone developer.

</public_display_of_affection>


I'm the author of the PragProg book on CoffeeScript (http://pragprog.com/book/tbcoffee/coffeescript), and I run @CoffeeScript on Twitter.

It's always fun to see a "CoffeeScript rocks" article like this explode on HN and Twitter. But it's even better to see stuff that people are building in CoffeeScript. The language has reached the point where it's gaining real traction in production settings, and not just among the beautiful code addicts at 37signals. There was a YC job posting about a week ago for a "CoffeeScript drinking frontend engineer" (http://news.ycombinator.com/item?id=2877677); they're also using CoffeeScript for a Node.js server, and even for MongoDB queries. I'm really excited to see that become a more common occurrence.


The bottleneck is never the time it takes to type the code.

Honestly, CoffeeScript is neat but it's not much of an improvement over JS. It's just as ugly and unreadable. It's only an improvement if you're counting characters.

I don't find CoffeeScript any less ugly or readable than JS. It seems incredibly redundent.


I'm sorry but what? Are python and ruby ugly and unreadable? Are they on the same level as js? Because coffeescript syntax is essentially a combination of the best aspects of both with a cleaner lambda syntax. I'd love to hear which languages you find beautiful and readable if cs doesn't meet your standards.


It's not about the time it takes to type code. Code that requires less typing is more succinct and therefore easier to read and understand.

You don't find it easier to read. Fair enough. I think a lot of people do. I personally found it much easier to write structured code in Coffeescript than in Javascript straight.


Agree to disagree about what is UGLY.


true we should all write machine code.


If someone likes x over y, it means they must like the most extreme thing possible that is different from y in the way x is!!

Why make that point? It has absolutely no intellectual content.


High-level languages are more than just syntactic sugar.


It seems like the removal of parenthesis is a bad idea, because it's bound to create a bunch of inconsistent code. Notice how all the rest of the code samples on the page keep the parenthesis in?


I approach this the same way I approach Ruby... I only use parenthesis when they improve readability of a confusing statement or are required (function call with another function call-with params-as a param). As you can see, this statement required parentheses ;-)


Yeah, I'm undecided yet as to which is best. My colleagues seem to be promoting keeping the parens in. Typically when we try stuff like this I like to push it to the max to see how it feels, then scale back.


I find it's a good smoke test for readability. Use parens to bind up atomic expressions in a line. If there are too many parens on a line, it's a good sign that you should break it up into two instead. It wouldn't be better lookin' with more.


It does create some inconsistency (even though CoffeeScript is in many ways one of the most consistent syntaxes I've seen) but you gain a lot in readability sometimes, and it makes it so easy to craft great domain-specific languages.


note: below the pics is an actual readworthy article.


Thanks for the heads up. I didn't get that far initially.


The problem with Coffeescript is if you already know JavaScript, it's completely unreadable. Looking at code like this, I have absolutely no idea what it does:

  class ItemView extends Backbone.View
    render: ->
      @options.items.each(@renderItem)
    renderItem: (item) =>
      @el.append item.get("title")
It doesn't make sense because there are magic variables appearing out of nowhere - @options, @el, append -- what are these? I'd have to study the resulting JavaScript to understand what it's really going to do.


I'm afraid you're getting tripped up by the Backbone.js library, not the language itself...

`this.options` is the options object that was passed when the View was created, and `this.el` is the default DOM element that wraps the View. For more info, see:

http://documentcloud.github.com/backbone/#View-constructor

http://documentcloud.github.com/backbone/#View-el


This is the major problem with CoffeeScript: it seems so straightforward, there must be something wrong with it.


I'd have to study the resulting JavaScript to understand what it's really going to do.

Once.

And then you could use shorter, more convenient syntax for the rest of your life. Worth it?


The same could be said of any language you are unfamiliar with. Ignoring the inheritance, which should be familiar to anyone with class-based OO experience, that code basically translates to:

    function ItemView() {
      this.render = function() {
        this.options.items.each(this.renderItem.bind(this));
      }

      this.renderItem = function(item) {
        this.el.append(item.get("title"))
      }
    }
In this example, I don't see any significant difference as far as readability goes, to be honest. I will note, in case it is not entirely clear, that the use of Backbone in the example is unrelated to CoffeeScript.


Except you left out setting the prototype chain to extend from the super class. CoffeeScript expresses it succinctly. The example above, while readable, already has much more noise than signal.


How is that not the case for any language?

(This also might be a bad example, but it was based off of code I wrote)


Coffeescript is adding an abstraction level, but all the complexity of JavaScript remains, so while you write Coffeescript, you have to sort of compile it in your head. I could maybe get on board if it went one whole level of abstraction further.


I disagree; I think the more standard handling of `this` and the automagic variable scoping, constitute a significant reduction in complexity for people coming from other OO languages. Certainly for me, having more experience with Python and Ruby than Javascript.

The abridged syntax is just gravy.


Just as a data point, most "on top of" languages seem a bit more distant from what they sit on top of.

In other words, C is somewhat cross platform, and much higher level than assembler. Ruby does way more out of the box than C does.

Coffeescript seems to mostly just be a modified JavaScript syntax, although I have to admit I haven't looked at it that closely.


That's all C++ originally was, too. Everything has to start somewhere, and fixing some of JavaScript's warts is as good a place to start as anywhere.


I've been playing around with coffeescript for a month now and I'm still undecided about whether these punctuation marks improve the syntax or not. Typing out "function" doesn't really take that long and it's much more readable than "->". On the other hand, I miss the parentheses and semi-colons. Without those punctuation marks the code feels more ambiguous. Maybe I'm just stuck in my ways, hopefully something will click soon.


I've used CoffeeScript extensively with a backbone.js project I was working on. I really liked it (and backbone).

But I haven't been able to bring it into my main rails app since I'd like to have all of my JS consistently in coffeescript. I don't like having both JS/CS, just like I don't like having HAML/ERB mixed together.

It would be a big project migrating it over and not as simple as HAMLizing a project.

Maybe one day I'll do it, or wait for a future rails projects.


There's a javascript to coffescript converter: https://github.com/rstacruz/js2coffee

Although I did have a few problems with some more complex code, it seemed to do the trick for more straightforward javascript. You'll lose your comments, but it's worth checking out.


First week of using CoffeeScript, I was mostly writing code and it felt foreign. Second week, same but it now felt convenient and I used it like a DSL. Third week, I was reading code as much as writing it and it suddenly became essential.

CS does have some rough spots that feels at odd with rest of the language but, overall, it brings clarity and convenience at minimal cost.


My only major complaint with Coffeescript is that it doesn't have a construct for handling the context-sensitive 'this' keyword. I still have to write

    self= @
at the top of functions. The fat arrow for binding 'this' certainly helps but when you have to be really careful when writing code that nests several functions.

Also, would be nice if the for-loop had a way to automatically wrap the block in a function without having to write

    for(var x in lst) do (x) ->
              whatever(x)


I'm not sure I understand your first complaint.

The fat arrow is a great helper and saves a lot of work in various situations....obviously it doesn't cover all situations...but in the situations it doen't cover I'm not sure what I'd expect the language to do.

Could you give an example of what you imagine the feature to be?

I'm just not sure if something as simple and easy as

    that = @
needs improvement. Anything beyond what that and => covers, to me seems like something a library should handle...and CS makes that very easy.

For you second one, what about

    do ( -> whatever x ) for x in foobar

One of the things I like about CS is that it is very conservative about not adding helpers for every little thing you can think of. It chooses a few very powerful and fundamental building blocks, and let's you use those to build up yourself.

I can respect some people wanting more though.


I did not know about the

    do () for x in foobar 
syntax. Thanks.


Sorry, my comment should read:

"""

    ( do (x) -> whatever x ) for x in foobar
or

    foo  = (x) -> whatever x
    foo x for x in foobar
or

    for x in foobar
        do (x) -> whatever x
I find all of these pretty readable and easy. The former in simple cases like "whatever x", and the latter two when you are doing more than just "whatever x".

I think it's important to distinguish cases like this and that the syntax is clean enough without adding some helper that makes what's going on implicit

"""

In the section where it says:

""" do ( -> whatever x ) for x in foobar """


Not sure that I understand you. Do you mean that you find it odd to use =>, and thus resort to self=@ for your callbacks?

Also, sometimes I do

    $.each lst, (i, item) ->
      whatever x
because I always use jQuery in my projects.


I often have to resort to self = @ when using jQuery in classes.

Because of how jQuery binds the queried element to this, and the fat arrow overrides this, there doesn't seem to be another way to access both your class and the jQuery element in the same function.

for instance:

    class ButtonLogger
    
      constructor: ->
        @clickedButtons = []
        
        $(document).ready => @init()

      init: ->
        self = @

        $('button').click ->
          $button = $(@)
          self.clickedButtons.push $button.attr 'id'


Try `event.currentTarget`, and `event.target` instead. They're much preferable to having a `self` (representing some random DOM element), and a `this` within a function.

    $('button').click (e) =>
      @clickedButtons.push $(e.target).attr 'id'


Perhaps the biggest strength of CoffeeScript is that it takes JavaScript, where there are many different ways to do OO inheritance; write and use functions; perform functional tasks such as list comprehension and provide a consistent and simplified syntax to do them. Because CoffeeScript is language designed how JS developers write code today, it feels more natural and fluid. It makes JS programming simpler.


Why raise so much snark straightaway about keywords, and then gripe about the silly ones later?

I've written thousands of lines of JavaScript, and a coupla hundred of CoffeeScript. CS is a usable, rather polished JS overlay, but I only understand it in terms of JS. In any case, I know which will be around longer.


>var html = "<option value='" + this.id + "'>" + this.get("title") + "</option>";

>This is such nonsense. Why did we put up with this? In CoffeeScript, you can write:

>html = "<option value='#{@id}'>#{@get("title")}</option>"

I have to say, the first one is much easier for me to read and understand.


The fat arrow by itself make it a mandate for everyone who wants to write OO js write Coffeescript.


Just thought I'd share the CoffeeScript + jQuery article in Septembers issue of Linux Journal:

http://www.linuxjournaldigital.com/linuxjournal/201109/?pg=3...


I agree that "function" is too long, but I'm not a huge fan of these arrow keywords because they're not very easy to type. But something like TextExpander would make a simple fix.


The arrows are easy enough for me. Middle finger hits the - or =, pinky hits shift and index finger hits >. It's drastically less finger-work than f-u-n-c-t-i-o-n-shift-(-)-space-{-}. The only languages I can think of off the top of my head with easier syntax for anonymous functions are Scala (a pair of parentheses is literally all you need) and Clojure (with its #() syntax), which both seem to have put a lot of effort into making them easy.

In particular, Ruby and Python both require more typing. At their most concise:

  Ruby:   -> {}

  Python: lambda:


You may be stuck with your IDE:

  JavaScript: fu<tab><shift-)>
    function(){
      <cursor>
    }

  Python: la<tab>:
The remaining characters should be filled in by most modern IDE / IDE plugins.


Those are both still more work than ->, and you could make a shortcut for the arrow as well if it's so difficult. Anyway, my point is that I don't see why the arrow should give anyone with a normal keyboard layout an inordinate amount of trouble compared to similar constructs in other languages.


Not easy to type? What kind of a weird alien keyboard do you have? :-)


points for using 300 to explain coffeescript


anybody wants to guess what this code compiles to?

  a [1] = 2




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: