Oops. I was hoping to post this to HN in a couple of days when it's finished, but the latest commits to CoffeeScript on Github include a compiler that's written entirely in CoffeeScript. It's been compiling itself since Friday.
This means that you can compile scripts in the browser, should you choose to, or within Node.js on the server, and greatly increases the speed of the interactive REPL. It's also a nice showcase for what's possible in CoffeeScript.
For example, take a peek at the Jison parser, using a little DSL function that makes for a nice style of grammar declaration:
If you'd like to play with the CoffeeScript-in-CoffeeScript implementation, use bin/node_coffee when you check out the source. bin/coffee remains the Ruby implementation until the CoffeeScript side is up to feature parity.
Here's the original post, things have come a long way since then:
For anyone who uses this in an app, my guess is that it makes debugging (in firebug etc) kinda annoying? I mean, even though it maps directly to JavaScript, the mental context switch between what you see in firebug and the code you've written would take getting used to?
We're trying to be pretty careful about keeping the compiled JS debuggable. To that end:
* The compiled output is pretty-printed instead of minified.
* Comments are passed through in-place to JavaScript.
* All functions are named functions, so instead of a stacktrace full of "anonymous", you can situate yourself.
* There's a "no special functions" rule -- CoffeeScript translates directly into JS without a standard library, which means that theres a one-to-one correspondence between your source code and its JavaScript equivalent, so it's not too hard to untangle.
That said, the temporary variable that we need to generate for some features are a little ugly, and sometimes we need to generate extra safety checks because we don't know certain things at compile time (such as, for example if a range counts upwards or down). Any suggestions for how to make the compiled JS more easily readable would be warmly welcomed.
My dream would be to be able to decompile JS into CoffeeScript, so I could make changes in either form. That would probably be difficult to do for some of the more advanced features, though.
Alright, just pushed a quick update to the documentation page that includes the self-compiler. You can try compiling CoffeeScript expressions in the browser right here:
Excellent work Jashkenas! I think what would really let you achieve liftoff (and a book deal with a tech publisher) would be a Sinatra-like framework based on this. The Sinatra core is very small and has wowed a lot of people, replicating it so that people are using coffeescript serverside and also in the client would be amazing. I imagine a 300 page book equally divided between the language, server-side and client-side would sell really well with a 1.0 release. I can easily picture a rails-like ecosystem (with associated business and publishing opportunities) surrounding this in the future.
require 'express'
require 'express/plugins'
configure ->
use MethodOverride
use ContentLength
set 'root', __dirname
get '/hello', ->
@contentType('html')
'<h1>Hello World </h1>'
get '/user/:id?', (id) ->
@render 'user.haml.html', {
locals: {
name: if id? then 'User '+id else 'You'
}
}
Is there a chance to add macros? Don't know enough about macros to know if it was doable for CoffeeScript, but only today I run into a situation where I thought it would be nice to have them in JS.
I am afraid it already slipped my mind as it was several hours ago. But I am sure another situation will arise. Where would be a good place to discuss it, as this thread will long have been gone stale by then?
Ah, the existential accessor operator is lovely. It really warms the heart to see variations on the Maybe monad sneaking into other languages--if there's one thing from Haskell I miss elsewhere, it's that.
Not 'less intuitive', it is 'less familiar'. These sorts of comments are largely subjective. See also C family programmers looking at Lisp or ML family languages.
Personally i don't care what someone who doesn't understand language X can make of a piece of code written in language X.
What I care about from a languages syntax is that it makes programs clear to someone familiar with the language.
Like i mention previously C family programmers often cannot make head or tail of a Lisp or ML family program, yet both those languages have excellent syntax where the choices made allow the programmer to express their intentions very clearly.
Contrast this with the popular view of Perl; One persons perl code can be impenetrable to another experienced perl programmer.
Syntax matters, but the familiarity with that syntax for outsides only matters from a purely political perspective. If you want to make a successful language, make it C flavored and baroque. If you want to make a truly great language, make the syntax that is best suited to what you are doing.
Isn't that the Python fallacy? (Take away the curly braces, anyhow.)
Programming is a lot more than syntax. How many non-programmers do you know who understand the semantics of mutable assignment without having it explained?
I'm glad you brought up mutable assignment. The reason for allowing colons as an alternative to equals signs in CoffeeScript is two-fold, the lesser reason is to make regular assignment consistent with JSON assignment, eg, both of these are legal CoffeeScript:
obj: {prop: val}
obj.prop: val
obj = {prop = val}
obj.prop = val
But the main reason is to avoid the equals sign as a symbol for assignment, because it has such a different meaning that you would expect in its use in math (unless immutable), where it implies the equivalence of the expressions on the left and right side for the entire duration of your proof.
Using colons, like JSON does to great effect, looks more like tagging a value with a label, which is much closer to the meaning of what you're actually doing in JS.
There's no question that the generated JavaScript is never going to be as pretty as handwritten JS. But that said, choosing splats as your example of bad syntax isn't the best choice, because there isn't a syntactic equivalent in JavaScript.
This CoffeeScript:
send_letter: (name, addresses...) ->
# more code...
Where the array of addresses can be referenced and used as many times as you like within the function body, would need to be translated as this JavaScript:
var send_letter = function send_letter(name) {
var addresses = Array.prototype.slice.call(arguments, 1);
# more code...
};
Which is both a good bit more to type, as well as more work -- you need to figure out the index from which to slice. The only difference with the generated JS is that the variable declaration is on a separate line -- a feature that allows all assignments to be used as part of a larger expression.
The braces are there because JavaScript's object literals are already pretty nice. But it would certainly be an interesting feature, if assigning to a block implied an object literal.
Okay, enough of these metalanguages. These languages might make it slightly easier to write your program, but the inability to use standard development tools with it results in you loosing more time in the end.
This means that you can compile scripts in the browser, should you choose to, or within Node.js on the server, and greatly increases the speed of the interactive REPL. It's also a nice showcase for what's possible in CoffeeScript.
For example, take a peek at the Jison parser, using a little DSL function that makes for a nice style of grammar declaration:
http://github.com/jashkenas/coffee-script/blob/master/src/gr...
If you'd like to play with the CoffeeScript-in-CoffeeScript implementation, use bin/node_coffee when you check out the source. bin/coffee remains the Ruby implementation until the CoffeeScript side is up to feature parity.
Here's the original post, things have come a long way since then:
http://news.ycombinator.com/item?id=1014080