Ruby on Training Wheels

A Weblog for Ruby and Rubyists.

Sugar in Your Coffee

JavaScript hurtin’ your Ruby-biased mind? Maybe a little coffee ‘n sugar is all you need!

When it comes to improving upon JavaScript, we have plenty of choices. Here I look at two of them: CoffeeScript and SugarJS.


“Learning JavaScript used to mean you weren’t a serious software developer. Today, not learning JavaScript means the same thing.” – Tim O’Reilly

These days, JavaScript is no longer an asset for a web-dev; it’s an absolute requirement. Unfortunately, it has been said that JavaScript has bad parts. That has been said to be an understatement.

Some History

Netscape mug

FWIW, this is not a judgment on Brendan Eich, who created JavaScript in 10 days back in May 1995. It was rushed out, rough edges and all, to preempt Microsoft’s attempt at an even worse proprietary language of their own, during the era of the Browser Wars, which in turn became the quintessential proof to “Always be Shipping!”

As JavaScripts community grew to include devs from other languages and disciplines, solutions sprang up to alert the presence of, side-step, and, in the case of CoffeScript, even solve these bad parts.

While there is some overlap in these solutions (particularly while trying to “shim” ECMA support in legacy browsers such as IE8), generally speaking they take different direction.

CoffeeScript

coffee with sugar

CoffeeScript is a language created by Jeremy Ashkenas (creator of the BackboneJS project among many others) which compiles directly to JavaScript. This means, you can’t serve .coffee files directly to the browser, rather it must first be compiled to a .js file first.

You can learn all about it on its homepage, where there’s a tool to run CoffeeScript in real-time. I’ll demonstrate just one example here. The basic tenets should be familiar to Rubyists:

  • Parens are optional
  • Semi-colons are banished
  • Implicit return statements
  • Lots of syntactic sugar
1
2
 Functions in CoffeeScript
logMsg = (msg) -> console.log "LOG: #{msg}" if loggingEnabled()

…compiles to:

1
2
3
4
5
6
7
var logMsg;

logMsg = function(msg) {
  if (loggingEnabled()) {
    return console.log("LOG: " + msg);
  }
};

SugarJS

Some coffee with your sugar sir?

SugarJS in it’s own words

… is a Javascript library that extends native objects with helpful methods. It is designed to be intuitive, unobtrusive, and let you do more with less code.

It has lots in common with Ruby, and even has a comparison page to see the syntactical differences between it and Ruby. So:

Ruby Syntax
1
2
3
4
# Count of Array Elements that are Odd:
arr.count { |n| n.odd? }
# Run Code n Times:
10.times {|n| puts n}
SugarJS Syntax
1
2
3
4
5
6
7
8
// Count of Array Elements that are Odd:
arr.count(function(n) {
  return n.isOdd();
});
// Run Code n Times:
(10).times(function(n){
    console.log(n);
});
Plain Jane JS
1
2
3
4
5
6
7
8
9
10
// Count of Array Elements that are Odd:
var result = 0;
for (var i = 0; i < arr.length; i++) {
  if (n % 2 !== 0) result++;
}
return result;
// Run Code n Times:
for (var n = 0; n < 10; n++) {
  console.log(n);
}

All Together Now

Because the fiat currency of the browser is JavaScript, as long as whichever shortcuts you use produce valid JavaScript, you can write code that intertwines all these examples.

CoffeeScript with a Dash of Sugar
1
2
3
4
5
6
7
app =
  foods: ['broccoli', 'spinach', 'chocolate']
  eatFoods: -> console.log food.capitalize() for food in @foods when food isnt 'chocolate'

$('a').click (e) ->
  e.preventDefault()
  app.eatFoods()
Equivalent JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var app;

app = {
  foods: ['broccoli', 'spinach', 'chocolate'],
  eatFoods: function() {
    var food, _i, _len, _ref, _results;
    _ref = this.foods;
    _results = [];
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      food = _ref[_i];
      if (food !== 'chocolate') {
        var first = food.slice(0, 1).toUpperCase();
        var rest = food.slice(1).toLowerCase();
        var foodCapitalized = first + rest;
        _results.push(console.log(foodCapitalized));
      }
    }
    return _results;
  }
};

$('a').click(function(e) {
  e.preventDefault();
  return app.eatFoods();
});

While there’s obviously an improvement in these example over the plain JS, if you’re having trouble understanding any of the plain JS code, you’re doing it wrong. Debugging will be ever more difficult if you don’t understand the “magic” in your code. (Anyone who has struggled with Rails and its particular form of magic can attest to this.) If you plan on writing client-heavy apps, there’s is no escaping learning JavaScript thoroughly, warts and all.

Conclusion

Being currently a student of a dynamic language (Ruby) and the ever-growing popularity of this family of languages (i.e. Perl, Python, PHP etc), I may never get to write any non-trivial apps in a language that need to get compiled. As CoffeeScript may be the closest I get, and to satisfy the requirement of at least one XKCD reference, I leave you with this:

303: ‘Are you stealing those LCDs?’ ‘Yeah, but I’m doing it while my code compiles.’


All Revisions to this document are visible here