Introduction to CoffeeScript by Jeremy Ashkenas

Last weekend, I was fortunate to have attended a CoffeeScript talk by no other than Jeremy Ashkenas. I was really lucky that Manila.js had organized this event to be really near my workplace such that I was able to sneak out during my break (huge thanks to Manila.js for organizing this event).

To be honest, I wasn’t really sure who Jeremy Ashkenas was before this event. So when I looked him up and found out he was the creator of CoffeeScript, that got me excited about this event. I had looked at CoffeeScript before and thought that it was just too much work for client-side scripting (CoffeeScript will need to be compiled to JavaScript). [I haven’t really done any server-side JS programming so my evaluation of CoffeeScript is based on my experience in client-side scripting.] But getting the introduction straight from the creator was still an eye-opener.

Here’s a summary of his talk:

Symbiotic Languages

Symbiotic Languages are languages that compile to another language’s bytecode or source code. There are more Symbiotic Languages nowadays due to more mature VMs or runtime environments.

One such example is the Java Virtual Machine (JVM). We’ve recently seen a proliferation of programming languages that run on top of the JVM. Some of these languages are not even semantically close to Java. Languages such as Clojure, JRuby, Jython and Scala have constructs that are alien to Java. Clojure and Scala support higher-order functions (although Project Lambda will allow Lambda expressions in Java 8) while JRuby and Jython are JVM implmentations of 2 of the most popular dynamic languages Ruby and Python.

A symbiotic language’s strength is that it allows morphing the original language’s constructs (this can be a complete paradigm shift but it still has limits) to suit a different application’s need (or even another programmer’s preference) and still run the compiled code on top of a stable environment.

CoffeeScript is just JavaScript

We’ve seen huge strides in JavaScript engines in the last 5-10 years. Google’s launch of Chrome and the V8 JavaScript Engine started this browser performance war between major browsers like Firefox, Chrome and IE.

It truly is impressive how JavaScript has improved since its inception in 1995. For a language that was designed in 10 days, it’s amazing how it got a lot of things right. Unfortunately, it still has some bad parts (Douglas Crockford’s JavaScript: The Good Parts is a great reference for this)…

CoffeeScript’s inspiration is using only the good parts. Coffeescript is a concise language that has syntax / structure borrowed from Ruby, Python and Haskell. It is compiled to an equivalent JavaScript that is guaranteed to pass through JSLint. As such, existing JavaScript libraries can work seamlessly with it.

CoffeeScript Demo

Here are some examples used in the talk. CoffeeScript codes and their equivalent translated JavaScript codes are provided in this section.

In CoffeeScript, everything is an expression.

print if one
  two
else
  three

In the code above, the return keyword can be omitted and the last line will be used as the value of the if-else expression that will be passed to the function print (parenthesis is also optional).

print(one ? two : three);

CoffeeScript is also smart enough to translate this piece of code to a ternary expression.

Expressions also allow the simplification of handling an error.

result = try
	missing.property
catch error
	error

console.log "The error is #{result}"

In the code above, result will be assigned the value of the valid expression if no error is encountered. It will be assigned the value of the error if there’s an error.

result = (function() {
  try {
    return missing.property;
  } catch (_error) {
    error = _error;
    return error;
  }
})();

console.log("The error is " + result);

CoffeeScript also support list comprehensions. This allows concise code for transforming a list.

print (transform item for item in list)

This translates to multiple lines in JavaScript.

print((function() {
  var _j, _len1, _results;

  _results = [];
  for (_j = 0, _len1 = list.length; _j < _len1; _j++) {
    item = list[_j];
    _results.push(transform(item));
  }
  return _results;
})());

It’s also easier to declare a class in CoffeeScript.

class Pirate
	hello: ->
		console.log 'yarr'

The usage of a class keyword provides a clearer usage for Pirate. It isn’t as clear when pure JavaScript is used due to the usage of the function keyword. The function is used for both function declaration and class declaration.

var Pirate;

Pirate = (function() {
  function Pirate() {}

  if (century > 1700) {
    Pirate.prototype.loot = function() {
      return say("Give me gold");
    };
  } else {
    ({
      loot: function() {
        return say("Arr");
      }
    });
  }

  return Pirate;

})();

CoffeeScript also allows the dynamic declaration of functions for a class. In this example, the definition of loot function can be determined at runtime.

class Pirate
	if century > 1700
		loot: ->
			say "Give me gold"
	else
		loot: ->
			say "Arr"
var Pirate;

Pirate = (function() {
  function Pirate() {}

  if (century > 1700) {
    Pirate.prototype.loot = function() {
      return say("Give me gold");
    };
  } else {
    ({
      loot: function() {
        return say("Arr");
      }
    });
  }

  return Pirate;

})();

Lastly, CoffeeScript allows the lexical scoping of the this keyword by using the fat arrow (=>)

class Book
	save: ->
		jQuery.ajax this.url, this.data, (response) => 
			merge this.data, response.data

This is especially useful for callback functions when using AJAX. In the code above, the this keyword in the response callback still refers to the Book class. In pure JavaScript, the this keyword is dynamically bound to the caller of the function.

This is how CoffeeScript handles or translates the this keyword within the fat arrow:

var Book;

Book = (function() {
  function Book() {}

  Book.prototype.save = function() {
    var _this = this;

    return jQuery.ajax(this.url, this.data, function(response) {
      return merge(_this.data, response.data);
    });
  };

  return Book;

})();

Conclusion

In this post, we’ve seen the strengths of CoffeeScript. It provides clear, concise and powerful constructs which allows us to write expressive code. CoffeeScript just translates to plain, clean JavaScript code which has a whole gamut of programming niceties. But will I use it?

I’d say yes and no. I really like how CoffeeScript shields us from JavaScript’s ugly parts and how it gives us extra powerful constructs that are sorely missing from JavaScript but I still think that the ease of debugging is very important. Imagine getting an error for a line no. that does not directly map to the source code that you’ve created. Yes, CoffeeScript preserves the names you use in your code, but it still is easier if we can get direct feedback from our debugger, right? Of course, this can change in the (near?) future (check out source map).

Advertisements