This post is part of my weekly tech learning series, where I take one hour each week to try out a piece of technology that I'd like to learn.
Today I decided to start my tech learning with CoffeeScript. CoffeeScript is "a little language that compiles into JavaScript" and has been really popular over the past year.
I know a good amount of JavaScript and have written a few JavaScript applications over the past few months so I was ready to see what improvements CoffeeScript includes.
Installing CoffeeScript was easy since I just used version 1.2.0 which is included in Ubuntu. It uses node which is surprising, I thought it was a RubyGem.
Todo App
For this session I decided to build a simple todo list. I have experience with them and it's a small enough application that I can try in later weeks.
Right off the bat the syntax was different, not better or worse than JavaScript but different. I think it might be a little better after some heavy usage due to it's sparseness (e.g. removing function()
, curly braces, and semi-colons).
Flow
Once I got into CoffeeScript, I quickly got into a flow.
- I had my coffee file open in one window,
- the CoffeeScript compiler in the background running
--watch
to rebuild my code, - and a console open with node to run my compiled JavaScript.
It wasn't quite a REPL nor was it TDD but I was able to cycle between code/build/test quickly. I ended up with a basic TodoList class that let you add, remove, count, and summarize your list of todos. Nothing fancy.
Node.js Problems
The biggest problem I ran into was with node.js. Since I didn't want to load everything into a browser I tried to build a small JavaScript program that would run in node. Since I was writing my application code in a separate file, getting it imported into node was a huge pain (eval
helped). I know I was doing something wrong, hopefully I can figure out the right way when I spend some time learning node.js later.
Summary
Overall I was happy with CoffeeScript. With a little bit of regular usage I should be just as productive as with JavaScript. I can see it being especially useful when needing to model things more into classes.
Code
# todo.coffee class TodoList constructor: -> @items = []
add: (todoItem) -> @items.push(todoItem)
remove: (todoItem) -> @items = _.reject @items, (existingTodo) -> existingTodo == todoItem
count: -> @items.length
summary: -> this.puts("==================================================") this.puts("= You have #{ this.count() } todo items") for todo in @items this.puts(todo) this.puts("--------------------------------------------------")
puts: (line) -> console.log(line)
# app.coffee
Node app
global._ = require("../vendor/underscore-min.js")
Hackery to get node to load todo.js in scope
eval(require('fs').readFileSync('lib/todo.js', 'utf8'));
Working on todo list
list = new TodoList() list.add("Install CoffeeScript") list.add("Install Node") list.add("Install coffee-mode") list.remove("Install CoffeeScript")
list.summary()
Compiled output:
var TodoList;
TodoList = (function() {
function TodoList() { this.items = []; }
TodoList.prototype.add = function(todoItem) { return this.items.push(todoItem); };
TodoList.prototype.remove = function(todoItem) { return this.items = _.reject(this.items, function(existingTodo) { return existingTodo === todoItem; }); };
TodoList.prototype.count = function() { return this.items.length; };
TodoList.prototype.summary = function() { var todo, _i, _len, _ref; this.puts("=================================================="); this.puts("= You have " + (this.count()) + " todo items"); _ref = this.items; for (_i = 0, _len = _ref.length; _i < _len; _i++) { todo = _ref[_i]; this.puts(todo); } return this.puts("--------------------------------------------------"); };
TodoList.prototype.puts = function(line) { return console.log(line); };
return TodoList;
})();
var list;
global._ = require("../vendor/underscore-min.js");
eval(require('fs').readFileSync('lib/todo.js', 'utf8'));
list = new TodoList();
list.add("Install CoffeeScript");
list.add("Install Node");
list.add("Install coffee-mode");
list.remove("Install CoffeeScript");
list.summary();