CoffeeScript

Why study CoffeeScript, even though it once had so much potential and a seemingly bright future? It’s a fabulous case study for transpilation. CoffeeScript is essentially JavaScript with a different, quite concise, syntax. Many of the features of CoffeeScript eventually made it into JavaScript proper.

Overview

The golden rule of CoffeeScript is: "It’s just JavaScript".

There used to be a great video introduction on blip.tv but that no longer exists. CoffeeScript is a lot less popular these days, because JavaScript really “caught up” over the years. When CoffeeScript debuted in 2009, JavaScript had very few features; since then JavaScript has added most of the things CoffeeScript enabled (spreads, destructuring, classes, string interpolation, and much more).

Be sure to check out the official CoffeeScript site, where you can learn CoffeeScript, and these two free books:

Getting Started

You can try out CoffeeScript on the little live compiler on the official CoffeeScript site, or run the standalone compiler and interpreter under Node.js.

Try CoffeeScript

The official CoffeeScript site has a live editor: start typing CoffeeScript code on the left side. The compiler runs as you type, and you’ll see the equivalent JavaScript taking shape on the right.

trycoffeescript.png

CoffeeScript in Node

Once you have node.js installed, you install CoffeeScript as a node package:

$ sudo npm install -g coffee-script

This creates a new executable on your system called "coffee". When run with no arguments you get a REPL:

$ coffee
coffee> 7 * 6 + 1 / 2
42.5
coffee> dogs = ["spike", "sparky", "spot"]
[ 'spike', 'sparky', 'spot' ]
coffee> (d.toUpperCase() for d in dogs)
[ 'SPIKE', 'SPARKY', 'SPOT' ]
coffee> _.length
3

Or you can execute CoffeeScript from the commandline:

fib.coffee
# Logs the Fibonacci numbers up to 100.

[a, b] = [0, 1]
while b <= 100
  console.log b
  [a, b] = [b, a + b]
$ coffee fib.coffee
1
1
2
3
5
8
13
21
34
55
89

Or you can do command line compilation from a CoffeeScript file, producing a JavaScript program which you can run with node:

$ coffee -c fib.coffee
$ cat fib.js
// Generated by CoffeeScript 2.6.0
(function() {
  // Logs the Fibonacci numbers up to 100.
  var a, b;

  [a, b] = [0, 1];

  while (b <= 100) {
    console.log(b);
    [a, b] = [b, a + b];
  }

}).call(this);
$ node fib.js
1
1
2
3
5
8
13
21
34
55
89

Some Examples

Why not start with Hello, world?

hello.coffee
console.log 'Hello, world'

And move the the classics. Fibonacci numbers:

fib.coffee
# Logs the Fibonacci numbers up to 100.

[a, b] = [0, 1]
while b <= 100
  console.log b
  [a, b] = [b, a + b]

Pythagorean triples:

triple.coffee
# This script prints some Pythagorean triples.

for c in [1..100]
  for b in [1..c]
    for a in [1..b]
      if a * a + b * b == c * c
        console.log "(#{a},#{b},#{c})"

An example of inheritance:

animals.coffee
# A typical example of inheritance

class Animal
  constructor: (@name) ->

  speak: ->
    "#{@name} says #{this.sound()}"

class Cow extends Animal
  sound: -> "moo"

class Horse extends Animal
  sound: -> "neigh"

class Sheep extends Animal
  sound: -> "baaaaa"

s = new Horse "CJ"
console.log s.speak()
c = new Cow "Bessie"
console.log c.speak()
console.log new Sheep("Little Lamb").speak()

Commandline arguments:

prefixes.coffee
# This script writes successive prefixes of its first command line
# argument to standard output.  It assumes that coffeescript is running
# under node.js, so the script would be invoked as
#
#   coffee prefixes.coffee thestringtogenerateprefixesof
#
# so the actual argument shows up at process.argv[2]

s = process.argv[2];
console.log s.slice(0, i) for i in [0..s.length] if s

Higher order functions:

hof.coffee
# Examples of higher order functions in CoffeeScript.
#
# This script contains both examples of defining your own higher order functions, and how you
# use the builtins map, reduce, and filter.

compose = (f, g) ->
  # Returns the functional composition of f and g
  (x) -> f g x

twice = (f) ->
  # Returns the function which applies f to its argument twice
  compose f, f

# Some plain old functions

isOdd = (x) -> x % 2 == 1
twoXPlusY = (x, y) -> 2 * x + y
square = (x) -> x * x
addSix = (x) -> x + 6

# The value of a variable can be a function

addSixThenSquare = compose square, addSix
addTwelve = twice addSix

# Illustration

console.log addSixThenSquare(9)    # 225
console.log twice(square)(3)       # 81
console.log addTwelve(100)         # 112

# map, filter, and reduce. map and filter are not used too much; comprehensions are
# generally more appropriate.

console.log [0..4].map square                       # [0, 1, 4, 9, 16]
console.log [0..6].filter isOdd                     # [1, 3, 5]
console.log [3, 6, -4, 2, -7].reduce(twoXPlusY, 0)  # 77

CoffeeScript in HTML

When writing a web app, you can compile your CoffeeScript files to JavaScript and include the resulting JavaScript from an HTML document. So given:

roll20.coffee
rolls = (Math.floor(Math.random() * 6) + 1 for i in [1..20])
div = document.createElement "div"
div.innerHTML = rolls
document.body.appendChild div

you would run:

$ coffee -c roll20.coffee

to produce roll20.js that you can include in:

roll20.html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>20 die rolls</title>
  </head>
  <body>
    <p>Rolling 20 dice</p>
    <script src="roll20.js"></script>
  </body>
</html>

Using a “build step” like this is better than including a CoffeeScript compiler in your HTML.

Language Features

A great way to learn CoffeeScript is to go through the documentation page. The page includes inline examples that you can run and even edit and re-run as you read in order to experiment. The documentation illustrates the following features:

The docs also cover setup and installation, a language reference, and list of resources (videos, books, tutorials), a language reference, and the use of associated tools such as cake.