James Williams
LinkedInMastodonGithub

Learning to love CoffeeScript

Tags: Gaming

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