University of Washington, CSE 154

Exploration Session: CoffeeScript

Except where otherwise noted, the contents of this document are Copyright © Marty Stepp, Jessica Miller, Victoria Kirst and Zachary Cava. All rights reserved. Any redistribution, reproduction, transmission, or storage of part or all of the contents in any form is prohibited without the author's expressed written permission.

Session and Slides by Zachary Cava

Valid HTML5 Valid CSS

CoffeeScript

What is CoffeeScript?

Getting Started with CoffeeScript

It is super simple to start working with CoffeeScript, in fact you don't even need to install anything on your computer. The team of engineers behind the language have created an amazing website that you can practice on: Coffeescript.org

You can also install the CoffeeScript interpreter with the following steps, examples given for Ubuntu:

Great Resources for CoffeeScript

CoffeeScript

Transforming JavaScript to CoffeeScript

There is one big change when coding in Coffeescript, there are no curly braces! Coffeescript uses whitespace to indent blocks, this is similar to Python and can take some getting use to. Here is a simple block of code in both JS and CS, we will talk about the other changes in a minute

JavaScript CoffeeScript
function somethingNew() {
	var old = true;
	if(old) {
		old = false;
	}
	return old;
}
						
somethingNew = ->
	old = true
	if old
		old = false
	return old
						

Functions

The syntax for creating a function is massively simplified

Name Javascript Syntax CoffeeScript Syntax
Declarations function name() { name = ->
w/ Arguments function name(arg1, arg2) { name = (arg1, arg2) ->
w/ Defaults
function name(arg1) {
if(arg1 == null) {
	arg1 = "default value";
}
(arg1 = "default value") ->
w/ Splats function name(arg1, arg2, arg3, arg4) { (arg1, others...) ->
Anonymous function() { ->
w/ Arguments function(arg1, arg2) { (arg1, arg2) ->

Objects/Arrays

Declaring arrays and objects has gotten easier as well

Name Javascript Syntax CoffeeScript Syntax
Array Declaration var data = [1, 2, 3, 4, 5]; data = [1, 2, 3, 4, 5]
Object Declaration
var person = {
	name : {
		first : "Zachary",
		last : "Cava"
	},
	email : "zcava@cs"
};
						
person = 
	name : 
		first : "Zachary"
		last : "Cava"
	email : "zcava@cs"
						

I would note that you can still declare objects with curly braces, it is typically only done when you want to use one line. Multiple lines should follow the indentation idiom

If/Else Statements

Like we said before, we signify blocks with whitespace, and if statements are the first time we will see this

Javascript Syntax CoffeeScript Syntax
if(test) {
	console.log("hi!");
} else if(othertest) {
	console.log("bye!");
} else {
	console.log("wat!");
}
						
if test
	console.log("hi!")
else if othertest
	console.log("bye!")
else
	console.log("wat!")

						
var data = test ? truths : falses var data = if test then truthes else falses

You may say, wait a second, turnary isn't any shorter! What the heck, this is suppose to be better!!

I promise there is a reason, we will get to it in due time young padawan

For Loops

At first the changes here might feel foreign, but as you see it more and more it will grow on you

Name Javascript Syntax CoffeeScript Syntax
For-Loop Exclusion
for(var i = 0; i < 20; i++) {
	// do something with i
}
						
for i in [0...20]
	# do something with i
						
For-Loop Inclusion
for(var i = 0; i <= 20; i++) {
	// do something with i
}
						
for i in [0..20]
	# do something with i
						

For-Each Loops

Coffeescript actually fixes the problems with the foreach loop that Javascript has!

Name Javascript Syntax CoffeeScript Syntax
For-Each Arrays
var data = [1, 2, 3, 4, 5];
for(var i = 0; i <= data.length; i++) {
	var item = data[i];
	// do something with item
}
						
data = [1, 2, 3, 4, 5]
for item in data
	# do something with item!
						
For-Each Objects
var name = {first: "Zachary", last: "Cava"}
for(key of name)
	if(name.hasOwnProperty(key)) {
		var value = name[key];
		// do something with key/value
	}
}
						
name = {first: "Zachary", last: "Cava"}
for key,value of name
	# do something with key/value!
						

CoffeeScript

Operators

Coffeescript has a aliases or replacements for a number of common operators in Javascript:

Javascript CoffeeScript
=== is
!== isnt
! not
&& and
|| or
true true, yes, on
false false, no, off
this @, this
in of
if(!condition) unless condition

Comprehensions

These additions were meant to bring a very typical functional program idiom to Javascript, if you have used Python before they will look familiar

Existential Operator

There are a number of times in Javascript that we want to use a value or a default if it hasn't been specified. Coffescript to the rescue!

newValue = possiblySet ? "default"

If possiblySet has been defined elsewhere before this line, then newValue will be set to the same value, but otherwise "default" will be used.

This is one of the reasons that turnary cannot exist in its normal form, the question mark operator is already used!

Existential Operator

The existential operator goes even further, you can use it to really cleanup lines where a bunch of conditions must be true.

if(data !== undefined && data.shouldCall !== undefined) {
	data.shouldCall();
}
				

Transforms to

data?.shouldCall?()

Woa! That just got crazy simpler, thats the power of CoffeeScript!

Conditional Evaluation

On a previous slide we saw how to do a list comprehension, but there is something much deeper at work here.

All statements are expressions (well most), and they can be prepended to a line to make them conditional, or repeated like in the case of the for-loop.

Combining the if statement with some expressions we get some very clean ways to have single line statements compacted and things like conditional returns which are common coffeescript idioms

Conditional Evaluation - Examples

Original Conditional
if neverNegative < 0
	neverNegative = 0
						
neverNegative = 0 if neverNegative < 0
if shouldWeStop
	return false
return false if shouldWeStop
if not shouldContinue
	return false
return false unless shouldContinue

Variable Scoping

Variable Scoping

Automatic scoping can be hard to understand and a little tricky to work with, these two blocks of code. Are they different?

Sample 1 Sample 2
someFunc = (arg1) ->
   inner = ->
       unless coolData?
            coolData = "No data :("
       console.log(coolData)
   coolData = "There is data!!!"

   inner()
someFunc = (arg1) ->
   coolData = "There is data!!!"
   inner = ->
       unless coolData?
            coolData = "No data :("
       console.log(coolData)

   inner()

Variable Scoping

Yes! Quite different! Here are the compiled versions, notice where the variable declarations are put. You need to pay close attention until you get use to it.

Sample 1 Sample 2
someFunc = function(arg1) {
  var coolData, inner;
  inner = function() {
    var coolData;
    if (typeof coolData === "undefined"
            || coolData === null) {
      coolData = "No data :(";
    }
    return console.log(coolData);
  };
  coolData = "There is data!!!";
  return inner();
};
someFunc = function(arg1) {
  var coolData, inner;
  coolData = "There is data!!!";
  inner = function() {
    if (coolData == null) {
      coolData = "No data :(";
    }
    return console.log(coolData);
  };
  return inner();
};

CoffeeScript

Objected Oriented JS

Declaring a Class

The syntax for declaring a class in CoffeeScript is quite similar to Python:

class Ball
	# stuff goes inside the class
				

Nothing too complex, everything you want to be in the class you simple indent inside the class!

Adding a Constructor

The constructor is a special keyword method, it can take whatever arguments you choose, and if you don't specify one it will simply do nothing.

class Ball
	constructor: (name) ->
		# do stuff in constructor

	#do other class stuff
				

Note that you can only have one constructor!

Adding Methods

To add a method you use syntax similar to the constructor, name: (args,...) ->

class Ball
	constructor: (name) ->
		# do stuff in constructor

	stepAnimation: ->
		# update ball state for one tick
				

Class Variables

One of the big uses of classes is the ability to store related information. To do this we use the @ symbol to reference the this object.

You don't need to declare a variable in a class before you use it, typically all variables in the class will be initialized somewhere in the constructor

class Ball
	constructor: (name) ->
		@name = name
		@yVelocity = 0
		@top = 0
				

Class Variables

Notice in the previous example we just take in name and set the class field of the same name to that value, there is actually a shorter way to write this:

class Ball
	constructor: (@name) ->
		@yVelocity = 0
		@top = 0

	getName: -> return @name

	getVelocity: -> return @yVelocity
				

Digression from the Slides

At this point we are going to fall away from the slides because the following graph illustrates the mind bendingness of the next topic: Inheritance

ITS OVER 9000!!!!!