Learning to love CoffeeScript
I recently came across the relatively new language CoffeeScript. For the initiated, CoffeeScript is a metalanguage for JavaScript. It can compile down to and consume JavaScript libraries. In polite terms, it is to JavaScript what Groovy is to Java. In more coarse terms, it's the bastard child of Python and Ruby that was raised by JavaScript.
Functions
Let's dive in and look a function from CoffeeScript:
square = (x) ->x*x
cube = (x) ->x * square x
The first thing that you'll notice is that there are no semicolons or curly braces. CoffeeScript doesn't need 'em. The next thing is significant whitespace like in Python. Outside of declaring the parameter list, we can also omit parentheses in most cases. They are needed for clarity or to differentiate between a no-parameter function and a property. Lastly, we don't need to pre-declare variables or even use the var keywaord. CoffeeScript can figure it out for us.
Conditionals
In addition to the ==, !=, &&, and || operators you would expect, CoffeeScript has equivalents in text that can be used interchangeably. So instead of writing
if result == 32 && bounds != null
we could write instead
if result is 32 and bounds isnt null
It has a slight Visual Basic feel to it but makes the code more readable.Another feature is that the conditional string can come after the code to evaluate. Something like the following is permitted.
x = 2 unless y is null
Classes and Inheritance
Simple declaration of classes is one area where CoffeeScript really shines. It's also where the Ruby influences come into play. In the classes below, we can see that instance properties are declared with an @ symbol. There is also a concept of super functions. They automatically invoke the parent function with the same name.
class Human
constructor: (@name) ->
@height
@gender
class Male extends Human
constructor: (@name) ->
super(@name)
@gender = "Male"
getHeight: ->
return @height + 3
In its raw JavaScript form, the above CoffeeScript compiles to
var Human, Male;
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
for (var key in parent) {
if (__hasProp.call(parent, key)) child[key] = parent[key];
}
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor;
child.__super__ = parent.prototype;return child;
};
Human = function() {
function Human(name) {
this.name = name;
this.height;
this.gender;
}return Human;
}();
Male = function() {
__extends(Male, Human);
function Male(name) {
this.name = name;
Male.__super__.constructor.call(this, this.name);
this.gender = "Male";
}
Male.prototype.getHeight = function() {
return this.height + 3;
};
return Male;
}
I don't know about you but I'd rather work with CoffeeScript than try to implement its features in raw JavaScript. For the book, I've been writing a game that uses the Canvas API with CoffeeScript. It's been awesome. I also recently gave a presentation where I ported a RESTful Java API to CoffeeScript.
For more information about CoffeeScript, visit: http://jashkenas.github.com/coffee-script