77 comments

[ 3.8 ms ] story [ 114 ms ] thread
i really like coffeescript.

one part i'm ambivalent about though is assignment and conditionals. there are too many ways to do the same thing, and i sit there wondering whether i'm using the "right" one.

Very interesting way to sell a programming language since haters gotta hate. I should have tried it with the programming language I wrote.
The slides didn't make a lot of sense (to me) without some sort of commentary. I presume from the title I'm not supposed to be familiar with the language.
I agree. The alternative examples were a bit confusing. Are they an alternative syntax or just an example of the "compiled" code?
This was a talk given by Tim at the JavaScript User Group Meeting Berlin in May 2010. There is also a video of the talk, but I can't find that anymore.
This is why I hate slideshare. It's like trying to watch a foreign film without the subtitles.
This is what, attempt number seven hundred and fifty two to create a mainstream language that encourages functional programming?

Incidentally, what's the most successful recent language that tries to make functional programming terser by not having an explicit "return" keyword (everything's an expression)? I'm genuinely curious, and don't think any significantly great number of programmers will ever find this style easier.

Ruby.

(Technically Ruby does have a return keyword, but it's optional. Same goes for CoffeeScript, I believe.)

ditto for Perl.
Not really: for example, if/else statements are not expressions whose results can be assigned to a variable like in Ruby.
This thread is about needing an implicit return. So my "ditto" is 100% correct!

But you are quite right that Perl if/else are statements and not expressions. Instead you can use the ternary operator:

    my $value = $cond == 1 ? 'true' : 'false';
And because of ditto for Perl you can also do following:

    my $value = do { if ($cond == 1) { 'true' } else { 'false' } };
CoffeeScript isn't an attempt to encourage functional programming so much as an attempt to combine the nice features of JS with a more modern syntax.
Is "square: (x) -> x*x" more modern syntax, or simply more functional? It surely isn't a new idea, maybe as old as Lisp, and a number of other new languages are explicitly imperative.
Perhaps even the syntax JS should have had from the beginning, with it's heavy Lisp inspiration.
I'm glad you picked out "everything is an expression" as the characteristic feature. I think that's completely correct -- everything else in the language is carefully compiled to make its use as part of a larger expression possible.

I don't, however, think that it's about functional programming. It's about flexibility: if everything is an expression, you can use any bit of code in relation to any other, and not worry about what parts of the languages are merely statements ... a JavaScript example being "var a = b", which cannot be used as part of a larger computation.

Having every function return a value is something that seems extraneous at first look, but ends up encouraging good API design. From the point of the caller of the function, returning a meaningful value is always appreciated -- even if it's as simple as returning "true" to acknowledge that the operation was completed successfully.

    int[] a = int[]{2,3,3,4}
    int s = a.Sum(i => i)
Thats C# by the way - lambda statements have implicit return statements.

Let me see, Ruby, Haskell and Scala uses this syntac.

I've been using CoffeeScript the last few weeks (writing a library using Raphael) and I'm really enjoying it. My one complaint is that the documentation has a few holes - in particular, it took me a little while to work out how to do block comments (### on either end), and more importantly, there's nowhere near enough documentation on cake. Right now my Cakefile uses child_process.exec, which is kind of lame and also doesn't show compilation errors.
What library are you writing?
It's for work - won't be widely distributed, I'm afraid.
Thanks for the documentation tips -- it's always helpful to hear what's missing from the perspective of a pair of fresh eyes. I've updated the documentation with an example of block comments:

http://jashkenas.github.com/coffee-script/#heredocs

And extended the section on "cake" a little bit with a better example that demonstrates passing in a command-line option. It sounds like your problem is different though -- here's the Node.js docs for child_process.exec:

http://nodejs.org/api.html#child_process-exec-95

You can use the "stderr" argument in the callback function to print the child's error output to the console. Running this bit of CoffeeScript, for example, will print out "to stderr":

    {exec}: require 'child_process'

    exec 'echo "to stderr" >&2', (err, stdout, stderr) ->
      print stderr
This right here is why CoffeeScript is so awesome. Jeremy is awesome, and continues to make it so.
Thanks Jeremy. I don't particularly want to use child_process.exec if there's a better/more direct way to compile, which it seems like there must be. I think it would be really helpful to have a dead simple Cakefile example for compiling a single CS file into a single JS file. It's not clear to me what the standard way to do that is, even with your new example.
I'm sorry -- if you'd like to use the compiler directly, here's an example:

    fs: require 'fs'

    fs.readFile source, (err, code) ->
      try
        js: CoffeeScript.compile(code.toString(), {source})
        fs.writeFile 'out.js', js
      catch err
        console.log err
Here's the source of the "CoffeeScript.compile" method:

http://jashkenas.github.com/coffee-script/documentation/docs...

Oh, cool, thanks. I also just learned that {source} is short for {source: source}. That's something else missing from the docs, I believe.
I was expecting that one of the reasons would be "JavaScript is a perfectly good language on its own."
I wouldn't say that JavaScript is "perfectly good." For instance, the statement "i=0" declares a global named i, unless there's a "var i" statement in a closer scope. It's a very, very easy mistake to make, and can lead to hours of debugging.

JavaScript is good, but CoffeeScript removes many of its imperfections, as well as offering a far better syntax.

jslint will help you to identify the global issue and takes seconds instead of hours.
Any time I have to reach for an external tool to figure out what's wrong with my program, I wonder if the language/framework/library/whatever could be improved to help prevent the problem in the first place. Valgrind much?
I'll never understand why some people are so opposed to learning new languages, especially one which won't change your current ecosystem and greatly improve your life (and quickly).
What's the debugging experience like?
As a source-to-source language, we try to keep debugging sane by outputting pretty-printed JavaScript that shouldn't be too hard to debug. For example, dropping you right into the middle of the JavaScript that's generated for the CoffeeScript Lexer looks like this:

http://github.com/jashkenas/coffee-script/blob/master/lib/le...

Pretty readable. You can use a Webkit or Firebug debugger just as you would with normal JS. It's a golden rule (with one small exception) that there are no CoffeeScript-specific constructs or special functions added to the runtime, no matter how tempting it might be to do so.

The single largest headache in practice is having to refer to the generated JS if the exception is vague, and just includes a line number. But I'm not sure that there's anything we can do to mitigate that, other than to keep the JS readable...

The debugging experience is surprisingly good. CoffeeScript is pretty much a one-to-one conversion into JavaScript. This makes it easy to work out which line of JavaScript was generated by which line of CoffeeScript, and debug the CoffeeScript directly.

I find I don't often need to look at the compiled JavaScript very often, but it is perfectly readable to do so if required.

I thoroughly hated that ignorant, nasty slide show displaying piece of crap used to present the stuff. It kept wresting control away from me so I couldn't view the slides at my own pace. What ever happened to text on a page, dammit?
Fake your UA to be iPad, and you'll get fast, clutter-free Slideshare.
if the OA would have just been plain text/images in HTML then everyone would get fast clutter-free with any web client, any platform, with less code, less complexity, etc.
It took me a while to learn to never hit the play button on slideshare. Always use the forward and back buttons next to play and you can advance at your own pace. Quite annoying.
I've recently been using CoffeeScript in conjunction with the Ojay wrapper for YUI (http://ojay.othermedia.org), which includes JS.Class ("Ruby-style JavaScript", http://jsclass.jcoglan.com/).

I've found the combination absolutely brilliant -- it recalls Ruby's creator Matz's promise of a language to "make programmers happy".

You get the expressiveness and brevity of Ruby, plus first-class functions, running in anyone's browser; and you get really well-thought-out event handling, AJAX and animation APIs.

I have only one serious pain-point with CoffeeScript: the Pythonesque significant whitespace. This commonly trips me up when providing anonymous function arguments to other functions (very common when assigning event listeners, for instance).

I guess the problem is that I never really understand exactly which whitespace is going to be deemed significant -- so maybe it's just a matter of documentation?

If you can show me a couple examples of places where the indentation tripped you up, I'd love to fix the documentation to explain them. Either starting a ticket, or gist-ing the examples here would be fine.

There was a question in #coffeescript last night about passing multiple anonymous functions into a function, and we came up with a couple of nice ways to write it:

http://gist.github.com/479249

Thanks. Obviously I've fixed the original problems now, but if I get a chance to try to recreate them I'll be in touch.

I should have mentioned that's the other thing to love about CoffeeScript: insanely responsive support!

The "try coffeescript" demo (http://jashkenas.github.com/coffee-script/) is really cool. It converts to javascript in realtime/as you type, including error checking on the fly.

I like the lambda syntax (I don't recall seeing exactly this syntax before):

    () -> alert("lambda")

    (() -> alert("lambda")) ()     # to call it
CoffeeScript lets you leave off parentheses when they're not necessary to describe what you mean. Your example can also be written as:

    -> alert 'lambda'

    (-> alert 'lambda')()  # to call it
It's a matter of opinion, but I don't particularly like when you can "omit" things.. and sometime it works and sometime it doesn't. Yes, sometime it makes the code a little clearer, but it can often lead to sneaky bugs and confusion.

I mean:

map x -> xx seq

might be readable ..

but:

map x -> xx seq seqs

is less clear.. while:

(map (x -> x*x) (seq seqs)) is more readable.

it also increases the friction when you are editing; the question in your mind must be "does this edit require the implicit to be made explicit?" Editor support can help alleviate the drudgery of the change, but I prefer to pay up-front.
aaronblohowiak, I wonder if "pay up front" is analogous to pre-mature optimization?

I'm thinking out loud, mainly because I tend to use the simplest syntax possible when coding in languages that allow for multiple syntaxes (i.e., Ruby). Most of the time, my decisions (at least) work out for me, and I don't have to go back and (say) add parentheses.

My two cents on optional parentheses, optional commas, and optional syntax in general are that it's about readability and style. If the statement that you're writing isn't clear without disambiguating the structure, then by all means, use parentheses. But if you're choosing between this:

    print("Hello");
And this:

    print "Hello"
(Which are equivalent in CoffeeScript) ... I'll take the latter every time.
That's very similar to the C# syntax

    () => expression
    arg => expression
    arg, arg2 => expression
    arg => { statement; expression }
It the compiled code compatible with the Strict mode in ECMAScript 5?

Did the language remove any of the "bad parts"?

In general, the compiled code should pass JavaScript lint without errors, and can be compatible with ECMA5 strict mode, but does not enforce it (because strict mode has a lot to do with runtime implementation, which we can't do anything about). Looking at page 233 of the spec:

http://www.ecma-international.org/publications/files/ECMA-ST...

Most of the strict mode restrictions have to do with "arguments" and "eval", which CoffeeScript doesn't affect. The two bits that we do enforce are: "Assignment to an undeclared identifier or otherwise unresolvable reference does not create a property in the global object," and "Strict mode code may not include a WithStatement" -- the former because variable scoping is automatic, and the latter because there is no "with" statement in CoffeeScript.

But there are a number of other, more important bad parts that are omitted, beyond strict mode: JavaScript's string-based switch statement, coercive equality checks, named function statements, trailing commas, and so on...

Just wrote an API in CoffeeScript, using Node.js and Express.

It was surprisingly enjoyable. I can see this ecosystem giving Rails/Sinatra/Django a real challenge. CoffeeScript makes ssjs a lot easier once you get used to it, Node.js gives you free non-blocking/high concurrency, and Express, which just released 1.0, is quickly maturing into a really solid DSL/web framework.

I'm excited to see how this ssjs scene unfolds.

I'm excited to see how the judicious use of JavaScript will evolve webapps beyond the Rails/Sinatra/Django paradigm, and allow you to share the code for your application between the client and the server. V8/Node.js is just the cherry on top:

http://shootout.alioth.debian.org/u32/code-used-time-used-sh...

Thanks to the effort put in by the V8 team, JavaScript is now an order of magnitude closer to C speed than Ruby, Python, and Perl, and sits at the same tranche of performance as OCaml and Go.

I'm working on a project that will let you share the same view code between rails, node and browsers. email me if this is something that you'd like to hack on (or check my github)
I presume you're referring to your EJSRB project:

http://github.com/aaronblohowiak/ejsrb/

I think that the usual way to share views between different languages is to use a language-agnostic templating engine, like Mustache, or Liquid.

How does EJSRB differ?

EJSRB is a full javascript context, and javascript is a language you probably already know. While our views are separate from controllers and models, they often need more advanced string manipulation than liquid or mustache give you. The fact that it is a full javascript context means you can define your own helpers, and have them still work on the client side. For instance, say you want to generate element ids from the json data. This belongs in a function that is accessible to your view layer, but you shouldn't have to program this twice (once for server, once for client.) AFAIK, there isn't a great way to accomplish this code sharing yet.
The really interesting language in that comparison is LuaJIT. It is faster and more concise than Javascript. It's sad that a mature, small, concise language like Lua doesn't have more traction outside niches.
I really enjoy working with Lua, though the opportunities have been infrequent. While Node.js looks like a wonderful piece of technology, every time I hear about it I feel a bit bitter that yet another opportunity to popularize Lua has been missed.
Lua fails in the "batteries included" domain. It is first and foremost developed as an extension language.

Furthermore, they are not really trying to promote the language beyond its current niches.

That said, there are good third party libraries and frameworks, and a Rubygems-like system called Lua Rocks.

yeah, but so does Javascript
But the one battery that is included in JS makes it unavoidable, and most programmers (the kind that don't read HN or proggit) are the kind to not want to learn another language. If you have the choice between using the quirky thing you know or learning something else, its a good bet most programmers will choose to use the tool the know, quality of the respective tools be damned ;)
"Batteries included" refers to a comprehensive standard library, which Javascript doesn't have.

The fact that Javascript is an in important feature in software that everyone runs is a whole different kind of advantage.

An included Web Browser with 99.99% of JavaScript interpreters is a pretty big battery.
I'd rather see Python move to the web client-side than JavaScript move to the web server-side. I would not kick JavaScript out of bed though.
JS absolutely has its faults, and you can hope all you want. But just by the simple fact that JavaScript is supported in every popular browser, and the browser is the largest application platform on the planet, means JS will soon to be the defacto standard language. Server & client-side.
That's really good, kudos. Any chance you could specify an option to leave array comprehensions/generator expressions alone for JS1.7+ platforms, btw?
Is the heredoc syntax for documentation? Or is it syntactic sugar for multiline text? Because that would be very nice.
It's syntactic sugar for multiline strings. It lets you write out formatted blocks of text that preserve indentation, allow you to use double-quotes and single-quotes inside without escaping, and because we have ECMA Harmony-style string interpolation -- you can interpolate values into heredocs as well.

For example, here's a hypothetical message:

    email: """
           Dear $recipient,

           You should receive your $product
           in the mail in $product.eta days.
           
           Thanks,
           $sender
           """
That's really nice, I would love that both for the above use of multiline text to be printed. But especially for client-side html templates.

I'm building my own javascript preprocessor language called O. I will definitely have to use that one, I hadn't thought of adding that. Should have considering it's in PHP, Pything, etc.

ps. I like the look of coffeescript, and the principle of having everything be an expression. What other kinds of properties does it enforce? Are you going to be adding any more features/property-preservations?

I'm trying to shoot for two interesting properties, 1) To be able to compile it back down to C/C++ for server side speed increases(Say in projects like Node.js where you can pretty easily hook in C/C++ modules. 2) To have the property of all code be reversable, and branchable for some interesting use cases. The reversability ties into some Networking/User-Interface Libs I'm making.

I'm curious what kind of tricks you used for implementing Coffeescript. Did you use hand made parsers, Parsing Expression Grammars, or base it on any other good projects?

Compiling a single language into JavaScript source code as well as C or C++ is going to be one hell of a trick. I think it'll be very difficult to keep the semantics the same, without resorting to running the equivalent of a JavaScript interpreter inside of your C++, but I wish you the best of luck with it.

If you'd like to discuss the implementation, feel free to drop by #coffeescript on freenode. But to give you the rough outline -- the compiler is made up of (in order), a Lexer, Rewriter, Parser, and AST of Nodes. The lexer creates the tokens, the rewriter rewrites the stream of tokens, disambiguating parses and allowing for optional syntax, the parser generates the AST of nodes, and then "compile()" is called on the root node, and walks down the tree, compiling the JavaScript string recursively.

For the parser, I'm using the excellent Jison parser generator for JavaScript, in LALR(1) mode. The only really unorthodox part of this is the Rewriter. It's not kosher to munge a token stream before parsing it -- but it's removed a ton of complexity from the grammar to not ever have to handle the syntactical edge cases, and to have them resolved in advance. All of the source is annotated, so here's some links:

* Jison: http://github.com/zaach/jison

* Lexer: http://jashkenas.github.com/coffee-script/documentation/docs...

* Rewriter: http://jashkenas.github.com/coffee-script/documentation/docs...

* Grammar: http://jashkenas.github.com/coffee-script/documentation/docs...

You are totally correct about the C/C++ generation not being easy if I go for making the whole language be elegantly compilable. I was thinking more of a subset, where you can mark a module or function(Not sure about the granularity) and it would raise a compile error if it doesn't maintain semantics that work elegantly in both Javascript and C/C++. It's really to allow Javascript programmers to not have to learn C/C++ and be able to accelerate their server side code (For say large image, or file processing. Or just expensive calculations like Pathfinding or Search-Space type stuff.) Of course it only works elegantly for server side, but it would be future proof for say using Native Client on the client side when or if it becomes available.

Thanks for the pointers, I remember now finding those implementation details when I leafed through your code a while back.

I'll check out the freenode channel when I get a chance.

I'm sold. Does it have a translator for all my old js, like sass-convert? And can I set it to watch a directory for changes and recompile if I save a file, like "compass watch"?
It doesn't have a translator from JS to Coffee, I'm afraid. There isn't a one-to-one mapping (ie. detecting when you're actually using a for loop as an array comprehension).

As for watching a directory for changes, absolutely. Just pass "--watch" to the "coffee" executable. For example:

    coffee --compile --watch --output lib src/
    
    coffee -cw -o lib src/
Which will watch "src" for changes, and compile all ".coffee" files inside to ".js" files in "lib", preserving the directory structure.
Excellent! I didn't think reverse translation would an easy problem for javascript, so I wasn't really expecting it.
I've been working with coffeescript all evening and I'm loving it. My one suggestion/complaint so far is that you should follow Python more closely in refusing to accept an assignment in conditionals and insisting on comparisons only, because it eliminates a lot of bugs. E.g. if I type

  if x = y
The compiler should raise a syntax error.
Glad you mentioned that point. The distinction between '=' and '==' in most programming languages is a personal pet peeve of mine. I think that it confuses two separate issues: labeling a value with a name, and testing the equality of values. Terrifically confusing stuff if you're coming from algebra.

So, although '=' is available to make transitioning from other languages smoother, idiomatic CoffeeScript would use ':' for assignment, both within and outside of object literals, and would use 'is' for equality. Harder to make a bug out of:

    if x is y
Thanks, I'd somehow missed "is" and "isnt" in the docs!