CoffeeScript

One of the benefits of JavaScript's massive popularity is that people who like to create new programming languages can write a translator from their new language to JavaScript. One such language, CoffeeScript is actually quite popular.

Introduction

The golden rule of CoffeeScript is: "It's just JavaScript". If you already know JavaScript it will be much easier to learn CoffeeScript. So go refresh your knowledge of JavaScript. Then, let's hear about CoffeeScript from Jeremy Ashkenas himself:

Be sure to check out the official CoffeeScript site and these two free books:

Getting Started

There are three main ways to run CoffeeScript

Try CoffeeScript

Go to the official CoffeeScript site, click on the TRY COFFEESCRIPT tab, and 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 HTML

This is not recommended for serious use, but it does work:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>20 die rolls</title>
  </head>
  <body>
    <p>Rolling 20 dice</p>
    <script src="http://jashkenas.github.com/coffee-script/extras/coffee-script.js"></script>
    <script type="text/coffeescript">
      rolls = (Math.floor(Math.random()*6)+1 for i in [1..20])
      div = document.createElement "div"
      div.innerHTML = rolls
      document.body.appendChild div
    </script>
  </body>
</html>

Scripts with type "text/coffeescript" run after the document is loaded.

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:

# 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
(function() {
  var a, b, _ref, _ref2;
  _ref = [0, 1], a = _ref[0], b = _ref[1];
  while (b <= 100) {
    console.log(b);
    _ref2 = [b, a + b], a = _ref2[0], b = _ref2[1];
  }
}).call(this);
$ node fib.js
1
1
2
3
5
8
13
21
34
55
89

Some Examples

Hello, world

console.log 'Hello, world'

Fibonacci numbers

# Logs the Fibonacci numbers up to 100.

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

Pythagorean triples

# 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

# 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

# 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

# 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

Language Features

One of the best ways 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), and the use of associated tools such as cake.