A Pull of the Lever: Prefaces

“We always pour our coffee in the ristretto, or restricted, tradition. The coffee is restricted to the most flavourful part of the shot. This tradition offers the heaviest shot, thickest texture and finest flavour that the coffee has to offer.”–David Schomer

About This Book

Learning about “for” loops is not learning to program, any more than learning about pencils is learning to draw.–Bret Victor, Learnable Programming

Programming languages are characterized by their syntax and their semantics. The syntax of a language defines its user interface; If you understand a language’s syntax, you understand what it makes easy. The semantics of a language defines its capabilities; If you understand a language’s semantics, you understand what it does well.

CoffeeScript Ristretto is first and foremost about a book about programming with functions, because its flexible and powerful functions are what make the CoffeeScript programming language so capable, and what CoffeeScript does well.

how this book is organized

CoffeeScript Ristretto begins at the beginning, with values and expressions, and builds from there to discuss types, identity, functions, closures, scopes, and many more subjects up to working with classes and instances in Chapter Five. Chapter Six, “An Extra Shot of Ideas,” introduces advanced CoffeeScript idioms like method decorators. Since CoffeeScript Ristretto is a book about CoffeeScript’s semantics, each topic is covered thoroughly, without hand-waving or simplification.

As a result, CoffeeScript Ristretto is a rich, dense read, much like the Espresso Ristretto beloved by coffee enthusiasts everywhere.

Foreword by Jeremy Ashkenas

“I particularly enjoyed this small book because I’ve reached for it a hundred times before and come up empty-handed. Large and heavy manuals on object-oriented programming and JavaScript are all around us, but to find a book that tackles the fundamental features of functions and objects in a brief, strong gulp, is rare indeed.

“With the inimitable Mr. Braithwaite as your guide, you’ll explore the nature of functions, the nooks and crannies of lexical scope, the essence of reference, the method of mutation, the construction of classes, callbacks, prototypes, promises, and more. And you’ll learn a great deal about the internals of CoffeeScript and the semantics of JavaScript along the way. Every feature is broken apart into its basic pieces, and you put it back together yourself, brick by brick.

“This book is dense, but hopefully you’ve chosen it because you like your ristretto bold and strong. If Reg had pulled it any thicker you’d have to chew it.”—Jeremy Ashkenas, CoffeeScript’s creator

Legend

Some text in monospaced type like this in the text represents some code being discussed. Some monospaced code in its own lines also represents code being discussed:

1 this . async = do ( async = undefined ) -> 2 3 async = ( fn ) -> 4 ( argv ..., callback ) -> 5 callback ( fn . apply ( this , argv ))

Sometimes it will contain some code for you to type in for yourself. When it does, the result of typing something in will often be shown using #=> , like this:

1 2 + 2 2 # => 4

A paragraph marked like this is a “key fact.” It summarizes an idea without adding anything new.

A paragraph marked like this is a suggested exercise to be performed on your own.

A paragraph marked like this is an aside. It can be safely ignored. It contains whimsey and other doupleplusunserious logorrhea that will not be on the test.

Prelude: Values and Expressions

The following material is extremely basic, however like most stories, the best way to begin is to start at the very beginning.

Imagine we are visiting our favourite coffee shop. They will make for you just about any drink you desire, from a short, intense espresso ristretto through a dry cappuccino, up to those coffee-flavoured desert concoctions featuring various concentrated syrups and milks. (You tolerate the existence of sugary drinks because they provide a sufficient profit margin to the establishment to finance your hanging out there all day using their WiFi and ordering a $3 drink every few hours.)

You express your order at one end of their counter, the folks behind the counter perform their magic, and deliver the coffee you value at the other end. This is exactly how the CoffeeScript environment works for the purpose of this book. We are going to dispense with web servers, browsers and other complexities and deal with this simple model: You give the computer an expression, and it returns a value, just as you express your wishes to a barista and receive a coffee in return.

values and expressions

All values are expressions. Say you hand the barista a Cafe Cubana. Yup, you hand over a cup with some coffee infused through partially caramelized sugar. You say, “I want one of these.” The barista is no fool, she gives it straight back to you, and you get exactly what you want. Thus, a Cafe Cubana is an expression (you can use it to place an order) and a value (you get it back from the barista).

Let’s try this with something the computer understands easily:

1 42

Is this an expression? A value? Neither? Or both?

The answer is, this is both an expression and a value.1 The way you can tell that it’s both is very easy: When you type it into CoffeeScript, you get the same thing back, just like our Cafe Cubana:

1 42 2 # => 42

All values are expressions. That’s easy! Are there any other kinds of expressions? Sure! let’s go back to the coffee shop. Instead of handing over the finished coffee, we can hand over the ingredients. Let’s hand over some ground coffee plus some boiling water.

Astute readers will realize we’re omitting something. Congratulations! Take a sip of espresso. We’ll get to that in a moment.

Now the barista gives us back an espresso. And if we hand over the espresso, we get the espresso right back. So, boiling water plus ground coffee is an expression, but it isn’t a value.2 Boiling water is a value. Ground coffee is a value. Espresso is a value. Boiling water plus ground coffee is an expression.

Let’s try this as well with something else the computer understands easily:

1 "CoffeeScript" + " " + "Ristretto" 2 # => "CoffeeScript Ristretto"

These are “strings,” values featured in almost every contemporary computer language. We see that “strings” are values, and you can make an expression out of strings and an operator + . Since strings are values, they are also expressions by themselves. But strings with operators are not values, they are expressions. Now we know what was missing with our “coffee grounds plus hot water” example. The coffee grounds were a value, the boiling hot water was a value, and the “plus” operator between them made the whole thing an expression that was not a value.

values and identity

In CoffeeScript, we test whether two values are identical with the is operator, and whether they are not identical with the isnt operator:

1 2 is 2 2 # => true 3 4 ' hello ' isnt ' goodbye ' 5 # => true

How does is work, exactly? Imagine that you’re shown a cup of coffee. And then you’re shown another cup of coffee. Are the two cups “identical?” In CoffeeScript, there are four possibilities:

First, sometimes, the cups are of different types. One is a demitasse, the other a mug. This corresponds to comparing two things in CoffeeScript that have different types. For example, the string "2" is not the same thing as the number 2 . Strings and numbers are different types, so strings and numbers are never identical:

1 2 is '2' 2 # => false 3 4 true isnt ' true ' 5 # => true

Second, sometimes, the cups are of the same type–perhaps two espresso cups–but they have different contents. One holds a single, one a double. This corresponds to comparing two CoffeeScript values that have the same type but different “content.” For example, the number 5 is not the same thing as the number 2 .

1 true is false 2 # => false 3 4 2 isnt 5 5 # => true 6 7 ' two ' is ' five ' 8 # => false

What if the cups are of the same type and the contents are the same? Well, CoffeeScript’s third and fourth possibilities cover that.

value types

Third, some types of cups have no distinguishing marks on them. If they are the same kind of cup, and they hold the same contents, we have no way to tell the difference between them. This is the case with the strings, numbers, and booleans we have seen so far.

1 2 + 2 is 4 2 # => true 3 4 ( 2 + 2 is 4 ) is ( 2 isnt 5 ) 5 # => true

Note well what is happening with these examples: Even when we obtain a string, number, or boolean as the result of evaluating an expression, it is identical to another value of the same type with the same “content.” Strings, numbers, and booleans are examples of what CoffeeScript calls “value” or “primitive” types. We’ll use both terms interchangeably.

We haven’t encountered the fourth possibility yet. Stretching the metaphor somewhat, some types of cups have a serial number on the bottom. So even if you have two cups of the same type, and their contents are the same, you can still distinguish between them.

reference types

So what kinds of values might be the same type and have the same contents, but not be considered identical to CoffeeScript? Let’s meet a data structure that is very common in contemporary programming languages, the Array (other languages sometimes call it a List or a Vector).

Here are some expressions for arrays you can try typing for yourself:

1 [1, 2, 3] 2 [1,2,2] 3 [1..3]

These are expressions, and you can combine [] with other expressions. Go wild with things like:

1 [2-1, 2, 2+1] 2 [1, 1+1, 1+1+1]

We aren’t going to spend a lot of time talking about it, but if you enable multiline mode (with ctrl-v), you can also type things like:

1 [ 2 1 3 2 4 3 5 ]

Notice that you are always generating arrays with the same contents. But are they identical the same way that every value of 42 is identical to every other value of 42 ? Try these for yourself:

1 [1..3] is [1,2,3] 2 [1,2,3] is [1, 2, 3] 3 [1, 2, 3] is [1, 2, 3]

How about that! When you type [1, 2, 3] or any of its variations, you are typing an expression that generates its own unique array that is not identical to any other array, even if that other array also looks like [1, 2, 3] . It’s as if CoffeeScript is generating new cups of coffee with serial numbers on the bottom.

They look the same, but if you examine them with is , you see that they are different. Every time you evaluate an expression (including typing something in) to create an array, you’re creating a new, distinct value even if it appears to be the same as some other array value. As we’ll see, this is true of many other kinds of values, including functions, the main subject of this book.

interlude…

Wikipedia on Ristretto:

”Ristretto is a very ‘short’ shot of espresso coffee. Originally this meant pulling a hand press faster than usual using the same amount of water as a regular shot of espresso. Since the water came in contact with the grinds for a much shorter time the caffeine is extracted in reduced ratio to the flavorful coffee oils. The resultant shot could be described as bolder, fuller, with more body and less bitterness.”

CoffeeScript Ristretto

The first sip: Functions

As Little As Possible About Functions, But No Less

In CoffeeScript, functions are values, but they are also much more than simple numbers, strings, or even complex data structures like trees or maps. Functions represent computations to be performed. Like numbers, strings, and arrays, they have a representation in CoffeeScript. Let’s start with the very simplest possible function. In CoffeeScript, it looks like this:3

1 ->

This is a function that is applied to no values and produces no value. Hah! There’s the third thing. How do we represent “no value” in CoffeeScript? We’ll find out in a minute. First, let’s verify that our function is a value:

1 -> 2 # => [ Function ]

What!? Why didn’t it type back -> for us? This seems to break our rule that if an expression is also a value, CoffeeScript will give the same value back to us. What’s going on? The simplest and easiest answer is that although the CoffeeScript interpreter does indeed return that value, displaying it on the screen is a slightly different matter. [Function] is a choice made by the people who wrote Node.js, the JavaScript environment that hosts the CoffeeScript REPL. If you try the same thing in a browser (using “Try CoffeeScript” at coffeescript.org for example), you’ll get something else entirely that isn’t CoffeeScript at all, it’s JavaScript.

I’d prefer something else, but I console myself with the thought that what gets typed back to us on the screen is arbitrary, and all that really counts is that it is somewhat useful for a human to read. But we must understand that whether we see [Function] or function () {} or–in some future version of CoffeeScript– -> , internally CoffeeScript has a full and proper function.4

functions and identities

You recall that we have two types of values with respect to identity: Value types and reference types. Value types share the same identity if they have the same contents.Reference types do not.

Which kind are functions? Let’s try it. For reasons of appeasing the CoffeeScript parser, we’ll enclose our functions in parentheses:

1 ( -> ) is ( -> ) 2 # => false

Like arrays, every time you evaluate an expression to produce a function, you get a new function that is not identical to any other function, even if you use the same expression to generate it. “Function” is a reference type.

applying functions

Let’s put functions to work. The way we use functions is to apply them to zero or more values called arguments. Just as 2 + 2 produces a value (in this case 4 ), applying a function to zero or more arguments produces a value as well. Some folks call the arguments the inputs to a function. Whether you use the word “inputs” or “arguments,” it’s certainly a good thing to think of the function’s arrow as pointing from the inputs to the output!

Here’s how we apply a function to some values in CoffeeScript: Let’s say that fn_expr is an expression that when evaluated, produces a function. Let’s call the arguments args. Here’s how to apply a function to some arguments:

fn_expr ( args )

Right now, we only know about one such expression: -> , so let’s use it. We’ll put it in parentheses5 to keep the parser happy, like we did above: (->) . Since we aren’t giving it any arguments, we’ll simply write () after the expression. So we write:

1 ( -> )() 2 # => undefined

What is this undefined ?

undefined

In CoffeeScript, the absence of a value is written undefined , and it means there is no value. It will crop up again. undefined is its own type of value, and it acts like a value type:

1 undefined 2 # => undefined

Like numbers, booleans and strings, CoffeeScript can print out the value undefined .

1 undefined is undefined 2 # => true 3 ( -> )() is ( -> )() 4 # => true 5 ( -> )() is undefined 6 # => true

No matter how you evaluate undefined , you get an identical value back. undefined is a value that means “I don’t have a value.” But it’s still a value :-)

Speaking of is undefined , a common pattern in CoffeeScript programming is to test wither something isnt undefined :

1 undefined isnt undefined 2 # => false 3 ' undefined ' isnt undefined 4 # => true 5 false isnt undefined 6 # => true

This is so common that a shortcut is provided, the suffix operator ? :

1 undefined ? 2 # => false 3 ' undefined ' ? 4 # => true 5 false ? 6 # => true

You might think that undefined in CoffeeScript is equivalent to NULL in SQL. No. In SQL, two things that are NULL are not equal to nor share the same identity, because two unknowns can’t be equal. In CoffeeScript, every undefined is identical to every other undefined .

functions with no arguments

Back to our function. We evaluated this:

1 ( -> )() 2 # => undefined

Let’s recall that we were applying the function -> to no arguments (because there was nothing inside of () ). So how do we know to expect undefined ? That’s easy. When we define a function, we write the arguments it expects to the left of the -> and an optional expression to the right. This expression is called the function’s body. Like this:

( args ) -> body

There is a funny rule: You can omit the body, and if you do, applying the function always evaluates to undefined .6

What about functions that have a body? Let’s write a few. Here’s the rule: We can use anything we’ve already learned how to use as an expression. Cutting and pasting, that means that the following are all expressions that evaluate to functions:

1 -> 2 2 -> 2 + 2 3 -> "Hello" + " " + "CoffeeScript" 4 -> true is not false 5 -> false isnt true

And you can evaluate them by typing any of these into CoffeeScript:

1 ( -> 2 )() 2 # => 2 3 ( -> 2 + 2 )() 4 # => 4 5 ( -> "Hello" + " " + "CoffeeScript" )() 6 # => "Hello CoffeeScript" 7 ( -> true is not false )() 8 # => true 9 ( -> false isnt true )() 10 # => true

We haven’t discussed arguments yet, but let’s get clever with what we already have.

functions that evaluate to functions

If an expression that evaluates to a function is, well, an expression, and if a function expression can have any expression on its right side… Can we put an expression that evaluates to a function on the right side of a function expression?

Yes:

1 -> ->

That’s a function! It’s a function that when applied, evaluates to a function that when applied, evaluates to undefined . Watch and see:

1 -> -> 2 # => [ Function ]

It evaluates to a function…

1 ( -> -> )() 2 # => [ Function ]

That when applied, evaluates to a function…

1 ( -> -> )()() 2 # => undefined

That when applied, evaluates to undefined . Likewise:

1 -> -> true

That’s a function! It’s a function that when applied, evaluates to a function, that when applied, evaluates to true :

1 ( -> -> true )()() 2 # => true

Well. We’ve been very clever, but so far this all seems very abstract and computer science-y. Diffraction of a crystal is beautiful and interesting in its own right, but you can’t blame us for wanting to be shown a practical use for it, like being able to determine the composition of a star millions of light years away. So… In the next chapter, “I’d Like to Have an Argument, Please,” we’ll see how to make functions practical.

showering felicitous encouragement to incentivise the practice of skewing the distribution of expression length towards the minimal mode

Or, In praise of keeping it short.

When describing the behaviour of functions, we often use the expression “that when applied, evaluates to…” For example, “The function (x, y) -> x + y is a function, that when applied to two integer arguments, evaluates to the sum of the arguments.”7 This is technically correct. But a mouthful. Another expression you will often hear is “returns,” as in “The function (x, y) -> x + y is a function that returns the sum of its arguments.”

“Returns” is a little less precise, and is context dependant. But it suits our purposes, so we will often use it. But when we use it, we will always mean “when applied, evaluates to…”

And with that’s let’s move on!

Ah. I’d Like to Have an Argument, Please.

Up to now, we’ve looked at functions without arguments. We haven’t even said what an argument is, only that our functions don’t have any.

Most programmers are perfectly familiar with arguments (often called “parameters”). Secondary school mathematics discusses this. So you know what they are, and I know that you know what they are, but please be patient with the explanation!

Let’s make a function with an argument:

1 ( room ) ->

This function has one argument, room , and no body. Here’s a function with two arguments and no body:

1 ( room , board ) ->

I’m sure you are perfectly comfortable with the idea that this function has two arguments, room , and board . What does one do with the arguments? Use them in the body, of course. What do you think this is?

1 ( diameter ) -> diameter * 3.14159265

It’s a function for calculating the circumference of a circle given the radius. I read that aloud as “When applied to a value representing the diameter, this function gives (that’s my word for the arrow) the diameter times 3.14159265.”

Remember that to apply a function with no arguments, we wrote (->)() . To apply a function with an argument (or arguments), we put the argument (or arguments) within the parentheses, like this:

1 (( diameter ) -> diameter * 3.14159265 )( 2 ) 2 # => 6.2831853

You won’t be surprised to see how to write and apply a function to two arguments:

1 (( room , board ) -> room + board )( 800 , 150 ) 2 # => 950

a quick summary of functions and bodies How arguments are used in a body’s expression is probably perfectly obvious to you from the examples, especially if you’ve used any programming language (except, possibly for the dialect of BASIC I recall from my secondary school that didn’t allow parameters when you called a procedure). Expressions consist either of representations of values (like 3.14159265 , true , and undefined ), operators that combine expressions (like 3 + 2 ), and some special forms like [1, 2, 3] for creating arrays out of expressions and ( arguments ) -> body-expression for creating functions. This loose definition is recursive, so we can intuit (or use our experience with other languages) that since a function has an expression on its right hand side, we can write a function that has a function as its expression, or an array that contains another array expression. Or a function that gives an array, an array of functions, a function that gives an array of functions, and so forth: 1 -> -> 2 -> [ 1 , 2 , 3 ] 3 [ 1 , [ 2 , 3 ], 4 ] 4 -> [( -> 1 ), ( -> 2 ), ( -> 3 )]

call by value

Like most contemporary programming languages, CoffeeScript uses the “call by value” evaluation strategy. That’s a $2.75 way of saying that when you write some code that appears to apply a function to an expression or expressions, CoffeeScript evaluates all of those expressions and applies the functions to the resulting value(s).

So when you write:

1 (( diameter ) -> diameter * 3.14159265 )( 1 + 1 ) 2 # => 6.2831853

What happened internally is that the expression 1 + 1 was evaluated first, resulting in 2 . Then our circumference function was applied to 2 .9

variables and bindings

Right now everything looks simple and straightforward, and we can move on to talk about arguments in more detail. And we’re going to work our way up from (diameter) -> diameter * 3.14159265 to functions like:

1 ( x ) -> ( y ) -> x

(x) -> (y) -> x just looks crazy, as if we are learning English as a second language and the teacher promises us that soon we will be using words like antidisestablishmentarianism. Besides a desire to use long words to sound impressive, this is not going to seem attractive until we find ourselves wanting to discuss the role of the Church of England in 19th century British politics. But there’s another reason for learning the word antidisestablishmentarianism: We might learn how prefixes and postfixes work in English grammar. It’s the same thing with (x) -> (y) -> x . It has a certain important meaning in its own right, and it’s also an excellent excuse to learn about functions that make functions, environments, variables, and more.

In order to talk about how this works, we should agree on a few terms (you may already know them, but let’s check-in together and “synchronize our dictionaries”). The first x , the one in (x) -> , is an argument. The y in (y) -> is another argument. The second x , the one in -> x , is not an argument, it’s an expression referring to a variable. Arguments and variables work the same way whether we’re talking about (x) -> (y) -> x or just plain (x) -> x .

Every time a function is invoked (“invoked” is a synonym for “applied to zero or more arguments”), a new environment is created. An environment is a (possibly empty) dictionary that maps variables to values by name. The x in the expression that we call a “variable” is itself an expression that is evaluated by looking up the value in the environment.

How does the value get put in the environment? Well for arguments, that is very simple. When you apply the function to the arguments, an entry is placed in the dictionary for each argument. So when we write:

1 (( x ) -> x )( 2 ) 2 # => 2

What happens is this:

CoffeeScript parses this whole thing as an expression made up of several sub-expressions. It then starts evaluating the expression, including evaluating sub-expressions One sub-expression, (x) -> x evaluates to a function. Another, 2 , evaluates to the number 2. CoffeeScript now evaluates applying the function to the argument 2 . Here’s where it gets interesting… An environment is created. The value ‘2’ is bound to the name ‘x’ in the environment. The expression ‘x’ (the right side of the function) is evaluated within the environment we just created. The value of a variable when evaluated in an environment is the value bound to the variable’s name in that environment, which is ‘2’ And that’s our result.

When we talk about environments, we’ll use an unsurprising syntax for showing their bindings: {x: 2, ...} . meaning, that the environment is a dictionary, and that the value 2 is bound to the name x , and that there might be other stuff in that dictionary we aren’t discussing right now.

call by sharing

Earlier, we distinguished CoffeeScript’s value types from its reference types. At that time, we looked at how CoffeeScript distinguishes objects that are identical from objects that are not. Now it is time to take another look at the distinction between value and reference types.

There is a property that CoffeeScript strictly maintains: When a value–any value–is passed as an argument to a function, the value bound in the function’s environment must be identical to the original.

We said that CoffeeScript binds names to values, but we didn’t say what it means to bind a name to a value. Now we can elaborate: When CoffeeScript binds a name to a value type value, it makes a copy of the value and places the copy in the environment. As you recall, value types like strings and numbers are identical to each other if they have the same content. So CoffeeScript can make as many copies of strings, numbers, or booleans as it wishes.

What about reference types? CoffeeScript cannot place a copy of an array or object in an environment, because the copy would not be identical to the original. So instead, CoffeeScript does not place reference values in any environment. CoffeeScript places references to reference types in environments, and when the value needs to be used, CoffeeScript uses the reference to obtain the original.

Because many references can share the same value, and because CoffeeScript passes references as arguments, CoffeeScript can be said to implement “call by sharing” semantics. Call by sharing is generally understood to be a specialization of call by value, and it explains why some values are known as value types and other values are known as reference types.

And with that, we’re ready to look at closures. When we combine our knowledge of value types, reference types, arguments, and closures, we’ll understand why this function always evaluates to true no matter what argument you apply it to:

1 ( value ) -> 2 (( copy ) -> 3 copy is value 4 )( value )

Closures and Scope

Before we explain (x) -> (y) -> x , we’re going to toss in something that doesn’t directly affect our explanation, but makes things easier to see visually. Up to now, every function has looked like this: ( arguments ) -> body. There’s another way to write functions. For example here’s the other way to write (x) -> x :

1 ( x ) -> 2 x

You get the idea: You can indent the body instead of putting it on the same line. Let’s introduce a new term: (x) -> is the function’s signature, and x is its body, just as we’ve mentioned before.

That means inductively we can also write (x) -> (y) -> x in two other ways:

1 ( x ) -> 2 ( y ) -> x

Or:

1 ( x ) -> 2 ( y ) -> 3 x

The indents help us see that the x is the body “belonging to” a function with signature (y) -> , and that it belongs to a function with signature (x) -> .

Time to see how a function within a function works:

1 (( x ) -> 2 ( y ) -> 3 x 4 )( 1 )( 2 ) 5 # => 1

First off, let’s use what we learned above. Given ( some function )( some argument ) , we know that we apply the function to the argument, create an environment, bind the value of the argument to the name, and evaluate the function’s expression. So we do that first with this code:

1 (( x ) -> 2 ( y ) -> 3 x 4 )( 1 ) 5 # => [ Function ]

The environment belonging to the function with signature (x) -> becomes {x: 1, ...} , and the result of applying the function is another function value. It makes sense that the result value is a function, because the expression for (x) -> ’s body is:

1 ( y ) -> 2 x

So now we have a value representing that function. Then we’re going to take the value of that function and apply it to the argument 2 , something like this:

1 (( y ) -> 2 x )( 2 )

So we seem to get a new environment {y: 2, ...} . How is the expression x going to be evaluated in that function’s environment? There is no x in its environment, it must come from somewhere else.

This, by the way, is one of the great defining characteristic of CoffeeScript and languages in the same family: Whether they allow things like functions to nest inside each other, and if so, how they handle variables from “outside” of a function that are referenced inside a function. For example, here’s the equivalent code in Ruby: 1 lambda { | x | 2 lambda { | y | x } 3 } [ 1 ][ 2 ] 4 #=> 1 Now let’s have an Espresso before we continue!

If functions without free variables are pure, are closures impure?

The function (y) -> x is interesting. It contains a free variable, x .10 A free variable is one that is not bound within the function. Up to now, we’ve only seen one way to “bind” a variable, namely by passing in an argument with the same name. Since the function (y) -> x doesn’t have an argument named x , the variable x isn’t bound in this function, which makes it “free.”

Now that we know that variables used in a function are either bound or free, we can bifurcate functions into those with free variables and those without:

Functions containing no free variables are called pure functions.

Functions containing one or more free variables are called closures.

Pure functions are easiest to understand. They always mean the same thing wherever you use them. Here are some pure functions we’ve already seen:

1 -> 2 3 ( x ) -> 4 x 5 6 ( x ) -> 7 ( y ) -> 8 x

The first function doesn’t have any variables, therefore doesn’t have any free variables. The second doesn’t have any free variables, because its only variable is bound. The third one is actually two functions, one in side the other. (y) -> has a free variable, but the entire expression refers to (x) -> , and it doesn’t have a free variable: The only variable anywhere in its body is x , which is certainly bound within (x) -> .

From this, we learn something: A pure function can contain a closure.

If pure functions can contain closures, can a closure contain a pure function? Using only what we’ve learned so far, attempt to compose a closure that contains a pure function. If you can’t, give your reasoning for why it’s impossible.

Pure functions always mean the same thing because all of their “inputs” are fully defined by their arguments. Not so with a closure. If I present to you this free function (x, y) -> x + y , we know exactly what it does with (2, 2) . But what about this closure: (y) -> x + y ? We can’t say what it will do with argument (2) without understanding the magic for evaluating the free variable x .

it’s always the environment

To understand how closures are evaluated, we need to revisit environments. As we’ve said before, all functions are associated with an environment. We also hand-waved something when describing our environment. Remember that we said the environment for ((x) -> (y) -> x)(1) is {x: 1, ...} and that the environment for ((y) -> x)(2) is {y: 2, ...} ? Let’s fill in the blanks!

The environment for ((y) -> x)(2) is actually {y: 2, '..': {x: 1, ...}} . '..' means something like “parent” or “enclosure” or “super-environment.” It’s (x) -> ’s environment, because the function (y) -> x is within (x) -> ’s body. So whenever a function is applied to arguments, its environment always has a reference to its parent environment.

And now you can guess how we evaluate ((y) -> x)(2) in the environment {y: 2, '..': {x: 1, ...}} . The variable x isn’t in (y) -> ’s immediate environment, but it is in its parent’s environment, so it evaluates to 1 and that’s what ((y) -> x)(2) returns even though it ended up ignoring its own argument.

(x) -> x is called the I Combinator or Identity Function. (x) -> (y) -> x is called the K Combinator or Kestrel. Some people get so excited by this that they write entire books about them, some are great, some–how shall I put this–are interesting if you use Ruby.

Functions can have grandparents too:

1 ( x ) -> 2 ( y ) -> 3 ( z ) -> 4 x + y + z

This function does much the same thing as:

1 ( x , y , z ) -> 2 x + y + z

Only you call it with (1)(2)(3) instead of (1, 2, 3) . The other big difference is that you can call it with (1) and get a function back that you can later call with (2)(3) .

The first function is the result of currying the second function. Calling a curried function with only some of its arguments is sometimes called partial application. Some programming languages automatically curry and partially evaluate functions without the need to manually nest them.

shadowy variables from a shadowy planet

An interesting thing happens when a variable has the same name as an ancestor environment’s variable. Consider:

1 ( x ) -> 2 ( x , y ) -> 3 x + y

The function (x, y) -> x + y is a pure function, because its x is defined within its own environment. Although its parent also defines an x , it is ignored when evaluating x + y . CoffeeScript always searches for a binding starting with the functions own environment and then each parent in turn until it finds one. The same is true of:

1 ( x ) -> 2 ( x , y ) -> 3 ( w , z ) -> 4 ( w ) -> 5 x + y + z

When evaluating x + y + z , CoffeeScript will find x and y in the great-grandparent scope and z in the parent scope. The x in the great-great-grandparent scope is ignored, as are both w s. When a variable has the same name as an ancestor environment’s binding, it is said to shadow the ancestor.

There can be spirited discussions over shadowing variables. Some people argue that shadowing is a good thing, as it allows small pieces of code to be understood without checking any enclosing environments. Others argue that it’s a bad thing, as it creates a confusing situation where two things with the same name actually are different things, a lot like naming both of your twins “Lesley.”

which came first, the chicken or the egg?

This behaviour of pure functions and closures has many, many consequences that can be exploited to write software. We are going to explore them in some detail as well as look at some of the other mechanisms CoffeeScript provides for working with variables and mutable state.

But before we do so, there’s one final question: Where does the ancestry start? If there’s no other code in a file, what is (x) -> x ’s parent environment?

CoffeeScript always has the notion of at least one environment we do not control: A global environment in which many useful things are bound such as libraries full of standard functions. So when you invoke ((x) -> x)(1) in the REPL, its full environment is going to look like this: {x: 1, '..': global environment } . When you use CoffeeScript to compile physical files for use in node or web applications, CoffeeScript does something interesting: It wraps your code in an invisible function, like this:

1 ( -> 2 (( x ) -> x )( 1 ) 3 )()

The effect of this is to insert a new, empty environment in between the global environment and your own functions: {x: 1, '..': {'..': global environment }} . As we’ll see when we discuss mutable state, this helps to prevent programmers from accidentally changing the global state that is shared by code in every file.

Summary

Functions Functions are values that can be part of expressions, returned from other functions, and so forth.

Functions are reference values.

Functions are applied to arguments.

The arguments are passed by sharing, which is also called “pass by value.”

Function bodies have zero or more expressions.

Function application evaluates to the value of the last expression evaluated or undedfined .

. Function application creates a scope. Scopes are nested and free variable references closed over.

Variables can shadow variables in an enclosing scope.

Slurp: More About Functions and Scope

Let Me Show You What To Do

let

Up to now, all we’ve really seen are anonymous functions, functions that don’t have a name. This feels very different from programming in most other languages, where the focus is on naming functions, methods, and procedures. Naming things is a critical part of programming, but all we’ve seen so far is how to name arguments.

There are other ways to name things in CoffeeScript, but before we learn some of those, let’s see how to use what we already have to name things. Let’s revisit a very simple example:

1 ( diameter ) -> 2 diameter * 3.14159265

What is this “3.14159265” number? Pi, obviously. We’d like to name it so that we can write something like:

1 ( diameter ) -> 2 diameter * Pi

In order to bind 3.14159265 to the name Pi , we’ll need a function with a parameter of Pi and an argument of 3.14159265 :

1 (( Pi ) -> 2 ??? 3 )( 3.14159265 )

What do we put inside our new function that binds 3.14159265 to the name Pi when evaluated? Our circumference function, of course:

1 (( Pi ) -> 2 ( diameter ) -> 3 diameter * Pi 4 )( 3.14159265 )

This expression, when evaluated, returns a function that calculates circumferences. It differs from our original in that it names the constant Pi. Let’s test it:

1 (( Pi ) -> 2 ( diameter ) -> 3 diameter * Pi 4 )( 3.14159265 )( 2 ) 5 # => 6.2831853

That works! We can bind anything we want and use it in a function by wrapping the function in another function that is immediately invoked with the value we want to bind. This “functional programming pattern” was popularized in the Lisp programming language more than 50 years ago, where it is called let .11 Although CoffeeScript doesn’t have a let keyword, when we discuss this programming pattern we will call it let .

let works,12 but only a masochist would write programs this way in CoffeeScript. Besides all the extra characters, it suffers from a fundamental semantic problem: there is a big visual distance between the name Pi and the value 3.14159265 we bind to it. They should be closer. Is there another way?

Yes.

do

CoffeeScript programmers often wish to create a new environment and bind some values to names within it as let does. To make this easier to read and write, CoffeeScript provides some syntactic sugar called do .13

This is what our example looks like using do :

1 do ( Pi = 3.14159265 ) -> 2 ( diameter ) -> 3 diameter * Pi

Much, MUCH cleaner.

If you need to create more than one binding, you separate them with commas:

1 do ( republican = ' Romney ' , democrat = ' Obama ' ) -> 2 democrat

The value on the right side can be any expression. Try this for yourself: 1 do ( Pi = 3.14159265 , diameter = (radius) -> radius * 2 ) -> 2 (radius) -> 3 diameter ( radius ) * Pi

Did you try the example above? Did you notice what we slipped in? Yes, obviously, the value of a binding can be any expression. But notice also that we can invoke a function on any expression evaluating to a function, including a variable that looks up a binding in the environment.

Dozens of pages into the book, we’re finally calling a function the way you’ll see functions being called in most production code. Sheesh.

A Simple Question

Both of the following produce the exact same result:

1 do ( Pi = 3.14159265 ) -> 2 ( diameter ) -> 3 diameter * Pi

And:

1 ( diameter ) -> 2 do ( Pi = 3.14159265 ) -> 3 diameter * Pi

Why do we habitually prefer the former?

To understand this, we’re going to take a simple step towards more complex, state-full programs by introducing sequences of expressions. If we had no other tools, we could evaluate a series of expressions with some legerdemain like this:

1 do ( ignore1 = foo (), 2 ignore2 = bar (), 3 ignore3 = blitz (), 4 value = bash ()) -> 5 bash

Or perhaps like this:

1 do ( ignore = [ foo (), bar (), blitz ()], value = bash ()) -> 2 bash

Or even this:

1 [ 2 foo () 3 bar () 4 blitz () ] and bash()

Any of these would evaluate foo() , bar() , blitz() , and then return the value of bash() (whatever they might be).

Why doesn’t foo() and bar() and blitz() and bash() work reliably?

But let’s learn another handy CoffeeScript feature, again because it helps us focus on what is actually going on. Whenever you want to work with the body of a function, you can always have it evaluate a simple sequence of one or more expressions by indenting them. The value of the body is the value of the final expression.

So in that case, we can write something like:

1 do -> 2 foo () 3 bar () 4 blitz () 5 bash ()

Anywhere a simple expression is allowed, you could use a do with a sequence. This doesn’t come up as much as you might think, because many of the places you want to do this, CoffeeScript already lets you indent and include more than one expression. For example, in a function body:

1 ( foo ) -> 2 bar ( foo ) 3 bash ( foo ) 4 foo ( ' blitz ' )

So back to our question. Here’s a test framework:

1 do ( circumference = do ( Pi = 3.14159265 ) -> 2 ( diameter ) -> 3 diameter * Pi ) -> 4 circumference ( 1 ) 5 circumference ( 2 ) 6 circumference ( 3 ) 7 circumference ( 4 ) 8 circumference ( 5 ) 9 circumference ( 6 ) 10 circumference ( 7 ) 11 circumference ( 8 ) 12 circumference ( 9 ) 13 circumference ( 10 ) 14 # => 31.4159265

Let’s think about how many functions we are invoking. When this is first invoked, We invoke the outer do (circumference = (...) -> . As part of doing that, we invoke do (Pi = 3.14159265) -> and bind the result to circumference . Then every time we invoke circumference , we invoke (diameter) -> . All together, twelve.

But with:

1 do ( circumference = ( diameter ) -> 2 do ( Pi = 3.14159265 ) -> 3 diameter * Pi ) -> 4 circumference ( 1 ) 5 circumference ( 2 ) 6 circumference ( 3 ) 7 circumference ( 4 ) 8 circumference ( 5 ) 9 circumference ( 6 ) 10 circumference ( 7 ) 11 circumference ( 8 ) 12 circumference ( 9 ) 13 circumference ( 10 ) 14 # => 31.4159265

What happens? There’s one outer do (circumference = (...) -> , same as before. And then every time we invoke circumference , we also invoke do (Pi = 3.14159265) -> , so we have a total of twenty-one function invocations. This is nearly twice as expensive.

Making Things Easy

In CoffeeScript Ristretto, we are focusing on CoffeeScript’s semantics, the meaning of CoffeeScript programs. As we go along, we’re learning just enough CoffeeScript to understand the next concept simply and directly.

CoffeeScript actually supports a number of syntactic conveniences for making programs extremely readable, by which we mean, making them communicate their intent without asking the programmer to struggle in a Turing Tarpit, no matter how elegant.

if i were a rich man

For example, it is possible to implement boolean logic using functions, by carefully combining the Identity ( (x) -> x ), Kestrel ( (x) -> (y) -> x ), and Vireo ( (x) -> (y) -> (z) -> z(x(y)) ) functions using a clever trick. It look something like this:

1 do ( I = (( x ) -> x ), 2 K = (( x ) -> ( y ) -> x ), 3 V = (( x ) -> ( y ) -> ( z ) -> z ( x ( y ))) 4 ) -> 5 do ( t = K , f = K ( I )) -> 6 # ... 7 # implement logical operators here 8 # ...

Did you notice that I slipped a new language feature in, one that allegedly allows a programmer to communicate their intent? Comments in CoffeeScript are signalled by a # and continue to the end of the line, much like // in C++ or JavaScript, and exactly like # in Ruby. If you have ever used C to make a comment line in FORTRAN, you are a real programmer and ought not to be fooling around with a quiche-eater’s language.

This is extraordinarily fascinating computer science stuff, but you can read about that elsewhere. CoffeeScript supplies true , false , and , or , and not so you don’t need to roll your own out of functions. But while we’re talking about logic, CoffeeScript also supplies conditional branches of execution, and we’ll use those in examples to come.

The syntax is remarkably simple. Here’s a conditional expression:

1 if d < 32 then ' freezing ' else ' warm '

Since it’s an expression, you can put it in parentheses and stick it anywhere you like, including inside another conditional:

1 ( d ) -> 2 if d < 32 then ' solid ' else if d < 212 then ' liquid ' else ' gas '

Like function bodies, there is an indented form that can be more readable:

1 ( d ) -> 2 if d < 32 3 ' solid ' 4 else 5 if d < 212 6 ' liquid ' 7 else 8 ' gas '

And the indented lines can have multiple expressions should you so desire:

1 if frobbish ? 2 alert ( "Frobbish value: #{frobbish}" ) 3 snarglivate ( frobbish ) 4 frobbish

Summary

More About Functions And Scope let is an idiom where we create a function and call it immediately in order to bind values to names.

is an idiom where we create a function and call it immediately in order to bind values to names. CoffeeScript uses do as syntactic sugar for let .

as syntactic sugar for . CoffeeScript’s comments are signalled with # .

. CoffeeScript has if , then , 'else and boolean logic.

interlude…

Michael Allen Smith on Ristretto:

“It must have been 1996. I was living in South Tampa at the time and the area finally got a great coffee house. The place was Jet City Espresso. Don’t go looking for it. It is no longer there. As the name implies, the owner Jessica was from Seattle and shared her coffee knowledge with her customers. After ordering numerous americanos and espressos, Jessica thought it was time I tried a ristretto. I expected the short pull of the espresso shot would result in a more bitter flavor. To my delight the shot was actually a sweeter and more intense version of her espresso blend.”

References, Identity, Arrays, and Objects

a simple question

Consider this code:

1 do ( x = ' June 14 , 1962 ' ) -> 2 do ( y = x ) -> 3 x is y 4 # => true

This makes obvious sense, because we know that strings are a value type, so no matter what expression you use to derive the value ‘June 14, 1962’, you are going to get a string with the exact same identity.

But what about this code?

1 do ( x = [ 2012 , 6 , 14 ]) -> 2 do ( y = x ) -> 3 x is y 4 # => true

Also true, even though we know that every time we evaluate an expression such as [2012, 6, 14] , we get a new array with a new identity. So what is happening in our environments?

arguments and references

In our discussion of closures, we said that environments bind values (like [2012, 6, 14] ) to names (like x and y ), and that when we use these names as expressions, the name evaluates as the value.

What this means is that when we write something like do (y = x) -> , the name x is looked up in the current environment, and its value is a specific array that was created when the expression [2012, 6, 14] was first evaluated. We then bind that exact same value to the name y in a new environment, and thus x and y are both bound to the exact same value, which is identical to itself.

The same thing happens with binding a variable through a more conventional means of applying a function to arguments:

1 do ( x = [ 2012 , 6 , 14 ]) -> 2 (( y ) -> 3 x is y )( x ) 4 # => true

x and y both end up bound to the exact same array, not two different arrays that look the same to our eyes.

arguments and arrays

CoffeeScript provides two different kinds of containers for values. We’ve met one already, the array. Let’s see how it treats values and identities. For starters, we’ll learn how to extract a value from an array. We’ll start with a function that makes a new value with a unique identity every time we call it. We already know that every function we create is unique, so that’s what we’ll use:

1 do ( unique = ( -> -> )) -> 2 3 unique () 4 # => [ Function ] 5 unique () is unique () 6 # false

Let’s verify that what we said about references applies to functions as well as arrays:

1 do ( x = unique ()) -> 2 do ( y = x ) -> 3 x is y 4 # => true

Ok. So what about things inside arrays? We know how to create an array with something inside it:

1 [ unique () ] 2 # => [ [ Function ] ]

That’s an array with one of our unique functions in it. How do we get something out of it?

1 do ( a = [ ' hello ' ]) -> 2 a [ 0 ] 3 # => ' hello '

Cool, arrays work a lot like arrays in other languages and are zero-based. The trouble with this example is that strings are value types in CoffeeScript, so we have no idea whether a[0] always gives us the same value back like looking up a name in an environment, or whether it does some magic that tries to give us a new value.

We need to put a reference type into an array. If we get the same thing back, we know that the array stores a reference to whatever you put into it. If you get something different back, you know that arrays store copies of things.14

Let’s test it:

1 do ( unique = ( -> -> )) -> 2 do ( x = unique ()) -> 3 do ( a = [ x ]) -> 4 a [ 0 ] is x 5 # => true

If we get a value out of an array using the [] suffix, it’s the exact same value with the same identity. Question: Does that apply to other locations in the array? Yes:

1 do ( unique = ( -> -> )) -> 2 do ( x = unique (), y = unique (), z = unique ()) -> 3 do ( a = [ x , y , z ]) -> 4 a [ 0 ] is x and a [ 1 ] is y and a [ 2 ] is z 5 # => true

references and objects

CoffeeScript also provides objects. The word “object” is loaded in programming circles, due to the widespread use of the term “object-oriented programming” that was coined by Alan Kay but has since come to mean many, many things to many different people.

In CoffeeScript, Objects15 are values that can store other values by name (including functions). The most common syntax for creating an object is simple:

1 { year : 2012 , month : 6 , day : 14 }

Two objects created this way have differing identities, just like arrays:

1 { year : 2012 , month : 6 , day : 14 } is { year : 2012 , month : 6 , day : 14 } 2 # => false

Objects use [] to access the values by name, using a string:

1 { year : 2012 , month : 6 , day : 14 }[ ' day ' ] 2 # => 14

Values contained within an object work just like values contained within an array:

1 do ( unique = ( -> -> )) -> 2 do ( x = unique (), y = unique (), z = unique ()) -> 3 do ( o = { a : x , b : y , c : z }) -> 4 o [ 'a' ] is x and o [ 'b' ] is y and o [ 'c' ] is z 5 # => true

Names needn’t be alphanumeric strings. For anything else, enclose the label in quotes:

1 { ' first name ' : ' reginald ' , ' last name ' : ' lewis ' }[ ' first name ' ] 2 # => ' reginald '

If the name is an alphanumeric string conforming to the same rules as names of variables, there’s a simplified syntax for accessing the values:

1 { year : 2012 , month : 6 , day : 14 }[ ' day ' ] is 2 { year : 2012 , month : 6 , day : 14 }. day 3 # => true

All containers can contain any value, including functions or other containers:

1 do ( Mathematics = { abs : ( a ) -> if a < 0 then - a else a }) -> 2 Mathematics . abs ( - 5 ) 3 # => 5

Funny we should mention Mathematics . If you recall, CoffeeScript provides a global environment that contains some existing object that have handy functions you can use. One of them is called Math , and it contains functions for abs , max , min , and many others. Since it is always available, you can use it in any environment provided you don’t shadow Math .

1 Math . abs ( - 5 ) 2 # => 5

Stir the Espresso: Objects, Mutation, and State

So far, we have discussed what many call “pure functional” programming, where every expression is necessarily idempotent, because we have no way of changing state within a program using the tools we have examined.

It’s time to change everything.

Reassignment and Mutation

Like most imperative programming languages, CoffeeScript allows you to re-assign the value of variables. The syntax is familiar to users of most popular languages:

1 do ( age = 49 ) -> 2 age = 50 3 age 4 # => 50

In CoffeeScript, nearly everything is an expression, including statements that assign a value to a variable, so we could just as easily write do (age = 49) -> age = 50 .

We took the time to carefully examine what happens with bindings in environments. Let’s take the time to fully explore what happens with reassigning values to variables. The key is to understand that we are rebinding a different value to the same name in the same environment.

So let’s consider what happens with a shadowed variable:

1 do ( age = 49 ) -> 2 do ( age = 50 ) -> 3 # yadda yadda 4 age 5 # => 49

Binding 50 to age in the inner environment does not change age in the outer environment because the binding of age in the inner environment shadows the binding of age in the outer environment. We go from:

1 { age : 49 , ' .. ' : global - environment }

To:

1 { age : 50 , ' .. ' : { age : 49 , ' .. ' : global - environment }}

Then back to:

1 { age : 49 , ' .. ' : global - environment }

However, if we don’t shadow age , reassigning it in a nested environment changes the original:

1 do ( age = 49 ) -> 2 do ( height = 1.85 ) -> 3 age = 50 4 age 5 # => 50

Like evaluating variable labels, when a binding is rebound, CoffeeScript searches for the binding in the current environment and then each ancestor in turn until it finds one. It then rebinds the name in that environment.

mutation and aliases

Now that we can reassign things, there’s another important factor to consider: Some values can mutate. Their identities stay the same, but not their structure. Specifically, arrays and objects can mutate. Recall that you can access a value from within an array or an object using [] . You can reassign a value using [] as well:

1 do ( oneTwoThree = [ 1 , 2 , 3 ]) -> 2 oneTwoThree [ 0 ] = ' one ' 3 oneTwoThree 4 # => [ ' one ' , 2 , 3 ]

You can even add a value:

1 do ( oneTwoThree = [ 1 , 2 , 3 ]) -> 2 oneTwoThree [ 3 ] = ' four ' 3 oneTwoThree 4 # => [ 1 , 2 , 3 , ' four ' ]

You can do the same thing with both syntaxes for accessing objects:

1 do ( name = { firstName : ' Leonard ' , lastName : ' Braithwaite ' }) -> 2 name . middleName = ' Austin ' 3 name 4 # => { firstName : ' Leonard ' , 5 # lastName : ' Braithwaite ' , 6 # middleName : ' Austin ' }

We have established that CoffeeScript’s semantics allow for two different bindings to refer to the same value. For example:

1 do ( allHallowsEve = [ 2012 , 10 , 31 ]) -> 2 halloween = allHallowsEve

Both halloween and allHallowsEve are bound to the same array value within the local environment. And also:

1 do ( allHallowsEve = [ 2012 , 10 , 31 ]) -> 2 do ( allHallowsEve ) -> 3 # ...

Hello, what’s this? What does do (allHallowsEve) -> mean? Well, when you put a name in the argument list for do -> but you don’t supply a value, CoffeeScript assumes you are deliberately trying to shadow a variable. It acts as if you’d written:

1 (( allHallowsEve ) -> 2 # ... 3 )( allHallowsEve )

There are two nested environments, and each one binds the name allHallowsEve to the exact same array value. In each of these examples, we have created two aliases for the same value. Before we could reassign things, the most important point about this is that the identities were the same, because they were the same value.

This is vital. Consider what we already know about shadowing:

1 do ( allHallowsEve = [ 2012 , 10 , 31 ]) -> 2 do ( allHallowsEve ) -> 3 allHallowsEve = [ 2013 , 10 , 31 ] 4 allHallowsEve 5 # => [ 2012 , 10 , 31 ]

The outer value of allHallowsEve was not changed because all we did was rebind the name allHallowsEve within the inner environment. However, what happens if we mutate the value in the inner environment?

1 do ( allHallowsEve = [ 2012 , 10 , 31 ]) -> 2 do ( allHallowsEve ) -> 3 allHallowsEve [ 0 ] = 2013 4 allHallowsEve 5 # => [ 2013 , 10 , 31 ]

This is different. We haven’t rebound the inner name to a different variable, we’ve mutated the value that both bindings share.

The same thing is true whenever you have multiple aliases to the same value:

1 do ( greatUncle = undefined , grandMother = undefined ) -> 2 greatUncle = { firstName : ' Leonard ' , lastName : ' Braithwaite ' } 3 grandMother = greatUncle 4 grandMother [ ' firstName ' ] = ' Lois ' 5 grandMother [ ' lastName ' ] = ' Barzey ' 6 greatUncle 7 # => { firstName : ' Lois ' , lastName : ' Barzey ' }

This example uses the letrec pattern for declaring bindings. Now that we’ve finished with mutation and aliases, let’s have a look at it.

letrec

One way to exploit reassignment is to “declare” your bindings with do and bind them to something temporarily, and then rebind them inline, like so:

1 do ( identity = undefined , kestrel = undefined ) -> 2 identity = ( x ) -> x 3 kestrel = ( x ) -> ( y ) -> x

This pattern is called letrec after the Lisp special form. Recall that let looks like this in CoffeeScript:

1 do ( identity = (( x ) -> x ), kestrel = ( x ) -> ( y ) -> x ) ->

To see how letrec differs from let , consider writing a recursive function16 like pow . pow takes two arguments, n and p , and returns n raised to the p th power. For simplicity, we’ll assume that p is an integer.

1 do ( pow = undefined ) -> 2 pow = ( n , p ) -> 3 if p < 0 4 1 / pow ( n , - p ) 5 else if p is 0 6 1 7 else if p is 1 8 n 9 else 10 do ( half = pow ( n , Math . floor ( p / 2 )), remainder = pow ( n , p % 2 )) -> 11 half * half * remainder

In order for pow to call itself, pow must be bound in the environment in which pow is defined. This wouldn’t work if we tried to bind pow in the do itself. Here’s a misguided attempt to create a recursive function using let :

1 do ( odd = ( n ) -> if n is 0 then false else not odd ( n - 1 )) -> 2 odd ( 5 )

To see why this doesn’t work, recall that this is equivalent to writing:

1 (( odd ) -> 2 odd ( 5 ) 3 )( ( n ) -> if n is 0 then false else not odd ( n - 1 ) )

The expression (n) -> if n is 0 then false else not odd(n-1) is evaluated in the parent environment, where odd hasn’t been bound yet. Whereas, if we wrote odd with letrec , it would look like this:

1 do ( odd = undefined ) -> 2 odd = ( n ) -> if n is 0 then false else not odd ( n - 1 ) 3 odd ( 5 )

Which is equivalent to:

1 (( odd ) -> 2 odd = ( n ) -> if n is 0 then false else not odd ( n - 1 ) 3 odd ( 5 ) 4 )( undefined )

Now the odd function is bound in an environment that has a binding for the name odd . letrec also allows you to make expressions that depend upon each other, recursively or otherwise, such as:

1 do ( I = undefined , K = undefined , T = undefined , F = undefined ) -> 2 I = ( x ) -> x 3 K = ( x ) -> ( y ) -> x 4 T = K 5 F = K ( I )

takeaway

CoffeeScript permits the reassignment of new values to existing bindings, as well as the reassignment and assignment of new values to elements of containers such as arrays and objects. Mutating existing objects has special implications when two bindings are aliases of the same value. The letrec pattern allows us to bind interdependent and recursive expressions.

Normal Variables

Now that we’ve discussed reassignment, it’s time to discuss assignment.

It sounds odd to say we’ve reassigned things without assigning them. Up to now, we’ve bound values to names through arguments, and do , which is really syntactic sugar for the let pattern.

In CoffeeScript, the syntax for assignment is identical to the syntax for reassignment:

1 birthday = { year : 1962 , month : 6 , day : 14 }

The difference comes when there is no value bound to the name birthday in any of the user-defined environments. In that case, CoffeeScript creates one in the current function’s environment. The current function is any of the following:

A function created with an arrow operator ( -> that we’ve seen, and => that we’ll see when we look at objects in more detail). A function created with the do syntax. When compiling CoffeeScript in files, an empty do -> is invisibly created to enclose the entire file.

One good consequence of this feature is that you can dispense with all of the nested do (...) -> expressions you’ve seen so far if you wish. You can boldly write things like:

1 identity = ( x ) -> x 2 kestrel = ( x ) -> ( y ) -> x 3 truth = kestrel 4 falsehood = kestrel ( identity )

You can also do your assignments wherever you like in a function, not just at the top. Some feel this makes code more readable by putting variable definitions closer to their use.

There are two unfortunate consequences. The first is that a misspelling creates a new binding rather than resulting in an error:

1 do ( age = 49 ) -> 2 # ... 3 agee = 50 4 # ... 5 age 6 # => 49 , not 50

The second is that you may accidentally alias an existing variable if you are not careful. If you’re in the habit of creating a lot of your variables with assignments rather than with do , you must be careful to scan the source of all of your function’s parents to ensure you haven’t accidentally reused the name of an existing binding.17

CoffeeScript calls creating new bindings with assignment “normal ,” because it’s how most programmers normally create bindings. Just remember that if anyone criticizes CoffeeScript for being loose with scoping and aliases, you can always show them how to use do to emulate let and letrec .

un-do

So, should we use do to bind variables or should we use “normal” variables? This is a very interesting question. Using do has a certain number of technical benefits. Then again, Jeremy Ashkenas, CoffeeScript’s creator, only uses do when it’s necessary, and most CoffeeScript programmers follow his lead. It hasn’t done them any harm.

So here’s what we suggest:

When writing new software, use Normal variables as much as possible. If and when you find there’s a scoping problem, you can refactor to do , meaning, you can change a normal variable into a variable bound with do to solve the problem.

Programming philosophy is a little outside of the scope of this book, but there is a general principle worth knowing: A good programmer is familiar with many design patterns, idioms, and constructions. However, the good programmer does not attempt to design them into every piece of code from the outset. Instead, the good programmer proceeds along a simple, direct, and clear path until difficulties arise. Then, and only then, does the good programmer refactor to a pattern. In the end, the code is simple where it does not solve a difficult or edge case, and uses a technique or idiom where there is a problem that needed solving.

do is a good pattern to know and deeply understand, but it is generally sufficient to write with normal variables. If you see a lot of do in this book, that is because we are writing to be excruciatingly clear, not to construct software that is easy to read and maintain in a team setting.

Comprehensions

If you’re the type of person who can “Write Lisp in any language,” you could set about writing entire CoffeeScript programs using let and letrec patterns such that you don’t have any normal variables. But being a CoffeeScript programmer, you will no doubt embrace normal variables. As you dive into CoffeeScript, you’ll discover many helpful features that aren’t “Lisp-y.” Eschewing them is to cut against CoffeeScript’s grain. One of those features is the comprehension, a mechanism for working with collections that was popularized by Python.

Here’s a sample comprehension:

1 names = [ ' algernon ' , ' sabine ' , ' rupert ' , ' theodora ' ] 2 3 "Hello #{yourName}" for yourName in names 4 # => [ ' Hello algernon ' , 5 # ' Hello sabine ' , 6 # ' Hello rupert ' , 7 # ' Hello theodora ' ]

An alternate syntax for the same thing that supports multiple expressions is:

1 for yourName in names 2 "Hello #{yourName}" 3 # => [ ' Hello algernon ' , 4 # ' Hello sabine ' , 5 # ' Hello rupert ' , 6 # ' Hello theodora ' ]

Here’s a question: There’s a variable reference yourName in this code. Is it somehow bound to a new environment in the comprehension? Or is it a “normal variable” that is either bound in the current function’s environment or in a parent function’s environment?

Let’s try it and see:

1 yourName = ' clyde ' 2 "Hello #{yourName}" for yourName in names 3 yourName 4 # => ' theodora '

It’s a normal variable. If it was somehow ‘local’ to the comprehension, yourName would still be clyde as the comprehension’s binding would shadow the current environment’s binding. This is usually fine, as creating a new environment for every comprehension could have performance implications.

However, there are two times you don’t want that to happen. First, you might want yourName to shadow the existing yourName binding. You can use do to fix that:

1 yourName = ' clyde ' 2 do ( yourName ) -> 3 "Hello #{yourName}" for yourName in names 4 yourName 5 # => ` clyde `

Recall that when you put a name in the argument list for do -> but you don’t supply a value, CoffeeScript assumes you are deliberately trying to shadow a variable. It acts as if you’d written:

1 yourName = ' clyde ' 2 (( yourName ) -> 3 "Hello #{yourName}" for yourName in names 4 )( yourName ) 5 yourName 6 # => ` clyde `

So technically, the inner yourName will be bound to the same value as the outer yourName initially, but as the comprehension is evaluated, that value will be overwritten in the inner environment but not the outer environment.

preventing a subtle comprehensions bug

Consider this variation of the above comprehension:

1 for myName in names 2 ( yourName ) -> "Hello #{yourName}, my name is #{myName}"

Now what we want is four functions, each of which can generate a sentence like “Hello reader, my name is rupert”. We can test that with a comprehension:

1 fn ( ' reader ' ) for fn in for myName in names 2 ( yourName ) -> "Hello #{yourName}, my name is #{myName}" 3 # => [ ' Hello reader , my name is theodora ' , 4 # ' Hello reader , my name is theodora ' , 5 # ' Hello reader , my name is theodora ' , 6 # ' Hello reader , my name is theodora ' ]

WTF!?

If we consider our model for binding, we’ll quickly discover the problem. Each of the functions we generate has a closure that consists of a function and a local environment. yourName is bound in its local environment, but myName is bound in the comprehension’s environment. At the time each closure was created, myName was bound to one of the four names, but at the time the closures are evaluated, myName is bound to the last of the four names.

Each of the four closures has its own local environment, but they share a parent environment, which means they share the exact same binding for myName . We can fix it using the “shadow” syntax for do :

1 fn ( ' reader ' ) for fn in for myName in names 2 do ( myName ) -> 3 ( yourName ) -> "Hello #{yourName}, my name is #{myName}" 4 # => [ ' Hello reader , my name is algernon ' , 5 # ' Hello reader , my name is sabine ' , 6 # ' Hello reader , my name is rupert ' , 7 # ' Hello reader , my name is theodora ' ]

Now, each time we create a function we’re first creating its own environment and binding myName there, shadowing the comprehension’s binding of myName . Thus, the comprehension’s changes to myName don’t change each closure’s binding.

takeaway

Comprehensions are extraordinarily useful for working with collections, but their loop variables are normal variables and may require special care to obtain the desired results. Also worth noting: Comprehensions may be the only place where let or do is necessary in CoffeeScript. Every other case can probably be handled with appropriate use of normal variables.

Encapsulating State with Closures

OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.–Alan Kay

We’re going to look at encapsulation using CoffeeScript’s functions and objects. We’re not going to call it object-oriented programming, mind you, because that would start a long debate. This is just plain encapsulation18, with a dash of information-hiding.

what is hiding of state-process, and why does it matter?

In computer science, information hiding is the principle of segregation of the design decisions in a computer program that are most likely to change, thus protecting other parts of the program from extensive modification if the design decision is changed. The protection involves providing a stable interface which protects the remainder of the program from the implementation (the details that are most likely to change).

Written another way, information hiding is the ability to prevent certain aspects of a class or software component from being accessible to its clients, using either programming language features (like private variables) or an explicit exporting policy.

Consider a stack data structure. There are three basic operations: Pushing a value onto the top ( push ), popping a value off the top ( pop ), and testing to see whether the stack is empty or not ( isEmpty ). These three operations are the stable interface.

Many stacks have an array for holding the contents of the stack. This is relatively stable. You could substitute a linked list, but in CoffeeScript, the array is highly efficient. You might need an index, you might not. You could grow and shrink the array, or you could allocate a fixed size and use an index to keep track of how much of the array is in use. The design choices for keeping track of the head of the list are often driven by performance considerations.

If you expose the implementation detail such as whether there is an index, sooner or later some programmer is going to find an advantage in using the index directly. For example, she may need to know the size of a stack. The ideal choice would be to add a size function that continues to hide the implementation. But she’s in a hurry, so she reads the index directly. Now her code is coupled to the existence of an index, so if we wish to change the implementation to grow and shrink the array, we will break her code.

The way to avoid this is to hide the array and index from other code and only expose the operations we have deemed stable. If and when someone needs to know the size of the stack, we’ll add a size function and expose it as well.

Hiding information (or “state”) is the design principle that allows us to limit the coupling between components of software.

how do we hide state using coffeescript?

We’ve been introduced to CoffeeScript’s objects, and it’s fairly easy to see that objects can be used to model what other programming languages call (variously) records, structs, frames, or what-have-you. And given that their elements are mutable, they can clearly model state.

Given an object that holds our state (an array and an index19), we can easily implement our three operations as functions. Bundling the functions with the state does not require any special “magic” features. CoffeeScript objects can have elements of any type, including functions:

1 stack = do ( obj = undefined ) -> 2 obj = 3 array: [] 4 index: - 1 5 push: ( value ) -> 6 obj . array [ obj . index += 1 ] = value 7 pop: -> 8 do ( value = obj . array [ obj . index ]) -> 9 obj . array [ obj . index ] = undefined 10 obj . index -= 1 if obj . index >= 0 11 value 12 isEmpty: -> 13 obj . index < 0 14 15 stack . isEmpty () 16 # => true 17 stack . push ( ' hello ' ) 18 # => ' hello ' 19 stack . push ( ' CoffeeScript ' ) 20 # => ' CoffeeScript ' 21 stack . isEmpty () 22 # => false 23 stack . pop () 24 # => ' CoffeeScript ' 25 stack . pop () 26 # => ' hello ' 27 stack . isEmpty () 28 # => true

method-ology

In this text, we lurch from talking about functions belong to an object to methods. Other languages may separate methods from functions very strictly, but in CoffeeScript every method is a function but not all functions are methods.

The view taken in this book is that a function is a method of an object if it belongs to that object and interacts with that object in some way. So the functions implementing the operations on the queue are all absolutely methods of the queue.

But these wouldn’t be methods. Although they belong to an object, they don’t interact with it:

1 { 2 min: ( x , y ) -> if x < y then x else y 3 max: ( x , y ) -> if x > y then x else y 4 }

hiding state

Our stack does bundle functions with data, but it doesn’t hide its state. “Foreign” code could interfere with its array or index. So how do we hide these? We already have a closure, let’s use it:

1 stack = do ( array = [], index = - 1 ) -> 2 push: ( value ) -> 3 array [ index += 1 ] = value 4 pop: -> 5 do ( value = array [ index ]) -> 6 array [ index ] = undefined 7 index -= 1 if index >= 0 8 value 9 isEmpty: -> 10 index < 0 11 12 stack . isEmpty () 13 # => true 14 stack . push ( ' hello ' ) 15 # => ' hello ' 16 stack . push ( ' CoffeeScript ' ) 17 # => ' CoffeeScript ' 18 stack . isEmpty () 19 # => false 20 stack . pop () 21 # => ' CoffeeScript ' 22 stack . pop () 23 # => ' hello ' 24 stack . isEmpty () 25 # => true

We don’t want to repeat this code every time we want a stack, so let’s make ourselves a “stack maker:”

1 StackMaker = -> 2 do ( array = [], index = - 1 ) -> 3 push: ( value ) -> 4 array [ index += 1 ] = value 5 pop: -> 6 do ( value = array [ index ]) -> 7 array [ index ] = undefined 8 index -= 1 if index >= 0 9 value 10 isEmpty: -> 11 index < 0 12 13 stack = StackMaker ()

Now we can make stacks freely, and we’ve hidden their internal data elements. We have methods and encapsulation, and we’ve built them out of CoffeeScript’s fundamental functions and objects. In Instances and Classes, we’ll look at CoffeeScript’s support for class-oriented programming and some of the idioms that functions bring to the party.

is encapsulation “object-oriented?” We’ve built something with hidden internal state and “methods,” all without needing special def or private keywords. Mind you, we haven’t included all sorts of complicated mechanisms to support inheritance, mixins, and other opportunities for debating the nature of the One True Object-Oriented Style on the Internet. Then again, the key lesson experienced programmers repeat (although it often falls on deaf ears) is, Composition instead of Inheritance. So maybe we aren’t missing much.

Composition and Extension

composition

A deeply fundamental practice is to build components out of smaller components. The choice of how to divide a component into smaller components is called factoring, after the operation in number theory 20.

The simplest and easiest way to build components out of smaller components in CoffeeScript is also the most obvious: Each component is a value, and the components can be put together into a single object or encapsulated with a closure.

Here’s an abstract “model” that supports undo and redo composed from a pair of stacks (see Encapsulating State) and a Plain Old CoffeeScript Object:

1 # helper function 2 shallowCopy = ( source ) -> 3 do ( dest = {}, key = undefined , value = undefined ) -> 4 dest [ key ] = value for own key , value of source 5 dest 6 7 # our model maker 8 ModelMaker = ( initialAttributes = {}) -> 9 do ( attributes = shallowCopy ( initialAttributes ), 10 undoStack = StackMaker (), 11 redoStack = StackMaker (), 12 obj = undefined ) -> 13 obj = { 14 set : ( attrsToSet = {}) -> 15 undoStack . push ( shallowCopy ( attributes )) 16 redoStack = StackMaker () unless redoStack . isEmpty () 17 attributes [ key ] = value for own key , value of attrsToSet 18 obj 19 undo : -> 20 unless undoStack . isEmpty () 21 redoStack . push ( shallowCopy ( attributes )) 22 attributes = undoStack . pop () 23 obj 24 redo : -> 25 unless redoStack . isEmpty () 26 undoStack . push ( shallowCopy ( attributes )) 27 attributes = redoStack . pop () 28 obj 29 get : ( key ) -> 30 attributes ( key ) 31 has : ( key ) -> 32 attributes . hasOwnProperty ( key ) 33 attributes : -> 34 shallowCopy ( attributes ) 35 } 36 obj

The techniques used for encapsulation work well with composition. In this case, we have a “model” that hides its attribute store as well as its implementation that is composed of of an undo stack and redo stack.

extension

Another practice that many people consider fundamental is to extend an implementation. Meaning, they wish to define a new data structure in terms of adding new operations and semantics to an existing data structure.

Consider a queue:

1 QueueMaker = -> 2 do ( array = [], head = 0 , tail = - 1 ) -> 3 pushTail: ( value ) -> 4 array [ tail += 1 ] = value 5 pullHead: -> 6 if tail >= head 7 do ( value = array [ head ]) -> 8 array [ head ] = undefined 9 head += 1 10 value 11 isEmpty: -> 12 tail < head

Now we wish to create a deque by adding pullTail and pushHead operations to our queue.21 Unfortunately, encapsulation prevents us from adding operations that interact with the hidden data structures.

This isn’t really surprising: The entire point of encapsulation is to create an opaque data structure that can only be manipulated through its public interface. The design goals of encapsulation and extension are always going to exist in tension.

Let’s “de-encapsulate” our queue:

1 QueueMaker = -> 2 do ( queue = undefined ) -> 3 queue = 4 array : [] 5 head: 0 6 tail: - 1 7 pushTail: ( value ) -> 8 queue . array [ queue . tail += 1 ] = value 9 pullHead: -> 10 unless queue . isEmpty () 11 do ( value = queue . array [ queue . head ]) -> 12 queue . array [ queue . head ] = undefined 13 queue . head += 1 14 value 15 isEmpty: -> 16 queue . tail < queue . head

Now we can extend a queue into a deque, with a little help from a helper function extend :

1 # helper function 2 extend = ( object , extensions ) -> 3 object [ key ] = value for key , value of extensions 4 object 5 6 # a deque maker 7 DequeMaker = -> 8 do ( deque = QueueMaker ()) -> 9 extend ( deque , 10 size : -> 11 deque . tail - deque . head + 1 12 pullTail : -> 13 unless deque . isEmpty () 14 do ( value = deque . array [ deque.tail ] ) -> 15 deque . array [ deque.tail ] = undefined 16 deque . tail -= 1 17 value 18 pushHead : do ( INCREMENT = 4 ) -> 19 ( value ) -> 20 if deque . head is 0 21 for i in [ deque.tail..deque.head ] 22 deque . array [ i + INCREMENT ] = deque . array [ i ] 23 deque . tail += INCREMENT 24 deque . head += INCREMENT 25 deque . array [ deque.head -= 1 ] = value 26 )

Presto, we have reuse through extension, at the cost of encapsulation.

Encapsulation and Extension exist in a natural state of tension. A program with elaborate encapsulation resists breakage but can also be difficult to refactor in other ways. Be mindful of when it’s best to Compose and when it’s best to Extend.

This and That

Let’s take another look at extensible objects. Here’s a Queue:

1 QueueMaker = -> 2 do ( queue = undefined ) -> 3 queue = 4 array : [] 5 head: 0 6 tail: - 1 7 pushTail: ( value ) -> 8 queue . array [ queue . tail += 1 ] = value 9 pullHead: do ( value = undefined ) -> 10 -> 11 unless queue . isEmpty () 12 value = queue . array [ queue . head ] 13 queue . array [ queue . head ] = undefined 14 queue . head += 1 15 value 16 isEmpty: -> 17 queue . tail < queue . head 18 19 queue = QueueMaker () 20 queue . pushTail ( ' Hello ' ) 21 queue . pushTail ( ' CoffeeScript ' )

Let’s make a copy of our queue using a handy extend function and a comprehension to make sure we copy the array properly:

1 extend = ( object , extensions ) -> 2 object [ key ] = value for key , value of extensions 3 object 4 5 copyOfQueue = extend ({}, queue ) 6 copyOfQueue . array = ( element for element in queue . array ) 7 8 queue isnt copyOfQueue 9 # => true

And start playing with our copies:

1 copyOfQueue . pullHead () 2 # => ' Hello ' 3 4 queue . pullHead () 5 # => ' CoffeeScript '

What!? Even though we carefully made a copy of the array to prevent aliasing, it seems that our two queues behave like aliases of each other. The problem is that while we’ve carefully copied our array and other elements over, the closures all share the same environment, and therefore the functions in copyOfQueue all operate on the first queue.

This is a general issue with closures. Closures couple functions to environments, and that makes them very elegant in the small, and very handy for making opaque data structures. Alas, their strength in the small is their weakness in the large. When you’re trying to make reusable components, this coupling is sometimes a hindrance.

Let’s take an impossibly optimistic flight of fancy:

1 AmnesiacQueueMaker = -> 2 array: [] 3 head: 0 4 tail: - 1 5 pushTail: ( myself , value ) -> 6 myself . array [ myself . tail += 1 ] = value 7 pullHead: do ( value = undefined ) -> 8 ( myself ) -> 9 unless myself . isEmpty ( myself ) 10 value = myself . array [ myself . head ] 11 myself . array [ myself . head ] = undefined 12 myself . head += 1 13 value 14 isEmpty: ( myself ) -> 15 myself . tail < myself . head 16 17 queueWithAmnesia = AmnesiacQueueMaker () 18 queueWithAmnesia . pushTail ( queueWithAmnesia , ' Hello ' ) 19 queueWithAmnesia . pushTail ( queueWithAmnesia , ' CoffeeScript ' )

The AmnesiacQueueMaker makes queues with amnesia: They don’t know who they are, so every time we invoke one of their functions, we have to tell them who they are. You can work out the implications for copying queues as a thought experiment: We don’t have to worry about environments, because every function operates on the queue you pass in.

The killer drawback, of course, is making sure we are always passing the correct queue in every time we invoke a function. What to do?

what’s all this ?

Any time we must do the same repetitive thing over and over and over again, we industrial humans try to build a machine to do it for us. CoffeeScript is one such machine:

1 BanksQueueMaker = -> 2 array: [] 3 head: 0 4 tail: - 1 5 pushTail: ( value ) -> 6 this . array [ this . tail += 1 ] = value 7 pullHead: do ( value = undefined ) -> 8 -> 9 unless this . isEmpty () 10 value = this . array [ this . head ] 11 this . array [ this . head ] = undefined 12 this . head += 1 13 value 14 isEmpty: -> 15 this . tail < this . head 16 17 banksQueue = BanksQueueMaker () 18 banksQueue . pushTail ( ' Hello ' ) 19 banksQueue . pushTail ( ' CoffeeScript ' )

Every time you invoke a function that is a member of an object, CoffeeScript binds that object to the name this in the environment of the function just as if it was an argument.22 Now we can easily make copies:

1 copyOfQueue = extend ({}, banksQueue ) 2 copyOfQueue . array = ( element for element in banksQueue . array ) 3 4 copyOfQueue . pullHead () 5 # => ' Hello ' 6 7 banksQueue . pullHead () 8 # => ' Hello '

Presto, we now have a way to copy arrays. By getting rid of the closure and taking advantage of this , we have functions that are more easily portable between objects, and the code is simpler as well.

Closures tightly couple functions to the environments where they are created limiting their flexibility. Using this alleviates the coupling. Copying objects is but one example of where that flexibility is needed.

fat arrows are the cure for obese idioms

Wait a second! Let’s flip back a few pages and look at the code for a Queue:

1 QueueMaker = -> 2 do ( queue = undefined ) -> 3 queue = 4 array : [] 5 head: 0 6 tail: - 1 7 pushTail: ( value ) -> 8 queue . array [ queue . tail += 1 ] = value 9 pullHead: -> 10 unless queue . isEmpty () 11 do ( value = queue . array [ queue . head ]) -> 12 queue . array [ queue . head ] = undefined 13 queue . head += 1 14 value 15 isEmpty: -> 16 queue . tail < queue . head

Spot the difference? Here’s the pullHead function we’re using now:

1 pullHead : do ( value = undefined ) -> 2 -> 3 unless this . isEmpty () 4 value = this . array [ this . head ] 5 this . array [ this . head ] = undefined 6 this . head += 1 7 value

Sneaky: The version of the pullHead function moves the do outside the function. Why? Let’s rewrite it to look like the old version:

1 pullHead: -> 2 unless this . isEmpty () 3 do ( value = this . array [ this . head ]) -> 4 this . array [ this . head ] = undefined 5 this . head += 1 6 value

Notice that we have a function. We invoke it, and this is set to our object. Then, thanks to the do , we invoke another function inside that. The function invoked by the do keyword does not belong to our object, so this is not set to our object. Oops!

Interestingly, this showcases one of CoffeeScript’s greatest strengths and weaknesses. Since everything’s a function, we have a set of tools that interoperate on everything the exact same way. However, there are some ways that functions don’t appear to do exactly what we think they’ll do. For example, if you put a return 'foo' inside a do , you don’t return from the function enclosing the do, you return from the do itself. And as we see, this gets set “incorrectly.” The Ruby programming language tries to solve this problem by having something–blocks–that look a lot like functions, but act more like syntax. The cost of that decision, of course, is that you have two different kinds of things that look similar but behave differently. (Make that five: Ruby has unbound methods, bound methods, procs, lambdas, and blocks.)

There are two solutions. The error-prone workaround is to write:

1 pullHead: -> 2 unless this . isEmpty () 3 do ( value = this . array [ this . head ], that = this ) -> 4 that . array [ that . head ] = undefined 5 that . head += 1 6 value

Besides its lack of pulchritude, there are many opportunities to mistakingly write this when you meant to write that . Or that for this . Or something, especially when refactoring some code.

The better way is to force the function to have the this you want. CoffeeScript gives you the “fat arrow” or => for this purpose. Here it is:

1 pullHead: -> 2 unless this . isEmpty () 3 do ( value = this . array [ this . head ]) => 4 this . array [ this . head ] = undefined 5 this . head += 1 6 value

The fat arrow says, “Treat this function as if we did the this and that idiom, so that whenever I refer to this , I get the outer one.” Which is exactly what we want if we don’t care to rearrange our code.

Summary

Objects, Mutation, and State CoffeeScript permits reassignment/rebinding of variables.

Arrays and Objects are mutable.

References permit aliasing of reference types.

The letrec pattern permits defining recursive or mutually dependent functions.

pattern permits defining recursive or mutually dependent functions. “Normal Case” variables are automagically scoped.

Comprehensions are convenient, but require care to avoid scoping bugs.

State can be encapsulated/hidden with closures.

Encapsulations can be aggregated with composition.

Encapsulation resists extension.

The automagic binding this facilitates sharing of functions.

facilitates sharing of functions. The fat arrow ( => ) is syntactic sugar for binding this .

Finish the Cup: Instances and Classes

As discussed in References, Identity, Arrays, and Objects and again in Encapsulating State, CoffeeScript objects are very simple, yet the combination of objects, functions, and closures can create powerful data structures. That being said, there are language features that cannot be implemented with Plain Old CoffeeScript Objects, functions, and closures23.

One of them is inheritance. In CoffeeScript, inheritance provides a cleaner, simpler mechanism for extending data structures, domain models, and anything else you represent as a bundle of state and operations.

Prototypes are Simple, it’s the Explanations that are Hard To Understand

As you recall from our code for making objects extensible, we wrote a function that returned a Plain Old CoffeeScript Object. The colloquial term for this kind of function is a “Factory Function.”

Let’s strip a function down to the very bare essentials:

1 Ur = ->

This doesn’t look like a factory function: It doesn’t have an expression that yields a Plain Old CoffeeScript Object when the function is applied. Yet, there is a way to make an object out of it. Behold the power of the new keyword:

1 new Ur () 2 # => {}

We got an object back! What can we find out about this object?

1 new Ur () is new Ur () 2 # => false

Every time we call new with a function and get an object back, we get a unique object. We could call these “Objects created with the new keyword,” but this would be cumbersome. So we’re going to call them instances. Instances of what? Instances of the function that creates them. So given i = new Ur() , we say that i is an instance of Ur .

For reasons that will be explained after we’ve discussed prototypes, we also say that Ur is the constructor of i , and that Ur is a constructor function. Therefore, an instance is an object created by using the new keyword on a constructor function, and that function is the instance’s constructor.

We are going to look at CoffeeScript’s class keyword later, but it’s worth noting that what CoffeeScript calls a constructor function does almost everything that people think of when they use the word “class.” It constructs instances, it defines their common behaviour, and it can be tested.

prototypes

There’s more. Here’s something you may not know about functions:

1 Ur . prototype 2 # => {}

What’s this prototype? Let’s run our standard test:

1 ( -> ). prototype is ( -> ). prototype 2 # => false

Every function is initialized with its own unique prototype . What does it do? Let’s try something:

1 Ur . prototype . language = ' CoffeeScript ' 2 3 continent = new Ur () 4 # => {} 5 continent . language 6 # => ' CoffeeScript '

That’s very interesting! Instances seem to behave as if they had the same elements as their constructor’s prototype. Let’s try a few things:

1 continent . language = ' JavaScript ' 2 continent 3 # => { language : ' JavaScript ' } 4 continent . language 5 # => ' JavaScript ' 6 Ur . prototype . language 7 ' CoffeeScript '

You can set elements of an instance, and they “override” the constructor’s prototype, but they don’t actually change the constructor’s prototype. Let’s make another instance and try something else.

1 another = new Ur () 2 # => {} 3 another . language 4 # => ' CoffeeScript '

New instances don’t acquire any changes made to other instances. Makes sense. And:

1 Ur . prototype . language = ' Sumerian ' 2 another . language 3 # => ' Sumerian '

Even more interesting: Changing the constructor’s prototype changes the behaviour of all of its instances. This strongly implies that there is a dynamic relationship between instances and their constructors, rather than some kind of mechanism that makes objects by copying.24

Speaking of prototypes, here’s something else that’s very interesting:

1 continent . constructor 2 # => [ Function ] 3 4 continent . constructor is Ur 5 # => true

Every instance acquires a constructor element that is initialized to their constructor. This is true even for objects we don’t create with new in our own code:

1 {}. constructor 2 # => [ Function : Object ]

If that’s true, what about prototypes? Do they have constructors?

1 Ur . prototype . constructor 2 # => [ Function ] 3 Ur . prototype . constructor is Ur 4 # => true

Very interesting! We will take another look at the constructor element when we discuss class extension.

revisiting this idea of queues

Let’s rewrite our Queue to use new and .prototype , using this and => :

1 extend = ( object , extensions ) -> 2 object [ key ] = value for key , value of extensions 3 object 4 5 Queue = -> 6 extend ( this , { 7 array: [] 8 head: 0 9 tail: - 1 10 }) 11 12 extend ( Queue . prototype , 13 pushTail: ( value ) -> 14 this . array [ this . tail += 1 ] = value 15 pullHead: -> 16 unless this . isEmpty () 17 do ( value = this . array [ this . head ]) => 18 this . array [ this . head ] = undefined 19 this . head += 1 20 value 21 isEmpty: -> 22 this . tail < this . head 23 )

You recall that when we first looked at this , we only covered the case where a function that belongs to an object is invoked. Now we see another case: When a function is invoked by the new operator, this is set to the new object being created. Thus, our code for Queue initializes the queue.

You can see why this is so handy in CoffeeScript: We wouldn’t be able to define functions in the prototype that worked on the instance if CoffeeScript didn’t give us an easy way to refer to the instance itself.

objects everywhere?

Now that you know about prototypes, it’s time to acknowledge something that even small children know: Everything in CoffeeScript behaves like an object, everything in CoffeeScript behaves like an instance of a function, and therefore everything in CoffeeScript behaves as if it inherits some methods from its constructor’s prototype and/or has some elements of its own.

For example:

1 3.14159265 . toPrecision ( 5 ) 2 # => ' 3.1415 ' 3 4 ' FORTRAN , SNOBOL , LISP , BASIC ' . split ( ' , ' ) 5 # => [ ' FORTRAN ' , 6 # ' SNOBOL ' , 7 # ' LISP ' , 8 # ' BASIC ' ] 9 10 [ ' FORTRAN ' , 11 ' SNOBOL ' , 12 ' LISP ' , 13 ' BASIC ' ]. length 14 #=> 5

Functions themselves are instances, and they have methods. For example, we know that CoffeeScript treats the fat arrow as if you were using the this and that idiom. But if you didn’t have a fat arrow and you didn’t want to take a chance on getting the idiom wrong, you could take advantage of the fact that every function has a method call .

Call’s first argument is a context: When you invoke .call on a function, it invoked the function, setting this to the context. It passes the remainder of the arguments to the function.

So, if we have:

1 pullHead: -> 2 unless this . isEmpty () 3 do ( value = this . array [ this . head ]) => 4 this . array [ this . head ] = undefined 5 this . head += 1 6 value

We could also write it like this:

1 pullHead: -> 2 unless this . isEmpty () 3 (( value ) -> 4 this . array [ this . head ] = undefined 5 this . head += 1 6 value 7 ). call ( this , this . array [ this . head ])

It seems like are objects everywhere in CoffeeScript!

impostors

You may have noticed that we use “weasel words” to describe how everything in CoffeeScript behaves like an instance. Everything behaves as if it was created by a function with a prototype.

The full explanation is this: As you know, CoffeeScript has “value types” like String , Number , and Boolean . As noted in the first chapter, value types are also called primitives, and one consequence of the way CoffeeScript implements primitives is that they aren’t objects. Which means they can be identical to other values of the same type with the same contents, but the consequence of certain design decisions is that value types don’t actually have methods or constructors. They aren’t instances of some constructor.

So. Value types don’t have methods or constructors. And yet:

1 "Spence Olham" . split ( ' ' ) 2 # => [ "Spence" , "Olham" ]

Somehow, when we write "Spence Olham".split(' ') , the string "Spence Olham" isn’t an instance, it doesn’t have methods, but it does a damn fine job of impersonating an instance of a String constructor. How does "Spence Olham" impersonate an instance?

CoffeeScript pulls some legerdemain. When you do something that treats a value like an object, CoffeeScript checks to see whether the value actually is an object. If the value is actually a primitive,25 CoffeeScript temporarily makes an object that is a kinda-sorta copy of the primitive and that kinda-sorta copy has methods and you are temporarily fooled into thinking that "Spence Olham" has a .split method.

These kinda-sorta copies are called String instances as opposed to String primitives. And the instances have methods, while the primitives do not. How does CoffeeScript make an instance out of a primitive? With new , of course. Let’s try it:

1 new String ( "Spence Olham" ) 2 # => "Spence Olham"

The string instance looks just like our string primitive. But does it behave like a string primitive? Not entirely:

1 new String ( "Spence Olham" ) is "Spence Olham" 2 # => false

Aha! It’s an object with its own identity, unlike string primitives that behave as if they have a canonical representation. If we didn’t care about their identity, that wouldn’t be a problem. But if we carelessly used a string instance where we thought we had a string primitive, we could run into a subtle bug:

1 if userName is "Spence Olham" 2 getMarried () 3 goCamping ()

That code is not going to work as we expect should we accidentally bind new String("Spence Olham") to userName instead of the primitive "Spence Olham" .

This basic issue that instances have unique identities but primitives withthe same contents have the same identities–is true of all primitive types, including numbers and booleans: If you create an instance of anything with new , it gets its own identity.

There are more pitfalls to beware. Consider the truthiness of string, number and boolean primitives:

1 if '' then ' truthy ' else ' falsy ' 2 # => ' falsy ' 3 if 0 then ' truthy ' else ' falsy ' 4 # => ' falsy ' 5 if false then ' truthy ' else ' falsy ' 6 # => ' falsy '

Compare this to their corresponding instances:

1 if new String ( '' ) then ' truthy ' else ' falsy ' 2 # => ' truthy ' 3 if new Number ( 0 ) then ' truthy ' else ' falsy ' 4 # => ' truthy ' 5 if new Boolean ( false ) then ' truthy ' else ' falsy ' 6 # => ' truthy '

Our notion of “truthiness” and “falsiness” is that all instances are truthy, even string, number, and boolean instances corresponding to primitives that are falsy.

There is one sure cure for “CoffeeScript Impostor Syndrome.” Just as new PrimitiveType(...) creates an instance that is an impostor of a primitive, PrimitiveType(...) creates an original, canonicalized primitive from a primitive or an instance of a primitive object.

For example:

1 String ( new String ( "Spence Olham" )) is "Spence Olham" 2 # => true

Getting clever, we can write this:

1 original = ( unknown ) -> 2 unknown . constructor ( unknown ) 3 4 original ( true ) is true 5 # => true 6 original ( new Boolean ( true ) is true 7 # => true

Of course, original will not work for your own creations unless you take great care to emulate the same behaviour. But it does work for strings, numbers, and booleans.

A Touch of Class

CoffeeScript has “classes,” for some definition of “class.” You’ve met them already, they’re constructors that are designed to work with the new keyword and have behaviour in their .prototype element. You can create one any time you like by:

Writing the constructor so that it performs any initialization on this , and: Putting all of the method definitions in its prototype.

This is simple enough, but there are some advantages to making it even simpler, so CoffeeScript does. Here’s our queue again:

1 class Queue 2 constructor: -> 3 extend ( this , 4 array: [] 5 head: 0 6 tail: - 1 7 ) 8 pushTail: ( value ) -> 9 this . array [ this . tail += 1 ] = value 10 pullHead: -> 11 unless this . isEmpty () 12 do ( value = this . array [ this . head ]) => 13 this . array [ this . head ] = undefined 14 this . head += 1 15 value 16 isEmpty: -> 17 this . tail < this . head 18 19 q = new Queue () 20 q . pushTail ( ' he