This is a book about getting computers to do what you want them to do. Computers are about as common as screwdrivers today, but they contain a lot more hidden complexity and thus are harder to operate and understand. To many, they remain alien, slightly threatening things.
We’ve found two effective ways of bridging the communication gap between us, squishy biological organisms with a talent for social and spatial reasoning, and computers, unfeeling manipulators of meaningless data. The first is to appeal to our sense of the physical world and build interfaces that mimic that world and allow us to manipulate shapes on a screen with our fingers. This works very well for casual machine interaction.
But we have not yet found a good way to use the point-and-click approach to communicate things to the computer that the designer of the interface did not anticipate. For open-ended interfaces, such as instructing the computer to perform arbitrary tasks, we’ve had more luck with an approach that makes use of our talent for language: teaching the machine a language.
Human languages allow words and phrases to be combined in many ways, which allows us to say many different things. Computer languages, though typically less grammatically flexible, follow a similar principle.
This book intends to make you familiar enough with this language to be able to make a computer do what you want.
I do not enlighten those who are not eager to learn, nor arouse those who are not anxious to give an explanation themselves. If I have presented one corner of the square and they cannot come back to me with the other three, I should not go over the points again.
There will be times when reading this book feels terribly frustrating. If you are new to programming, there will be a lot of new material to digest. Much of this material will then be combined in ways that require you to make additional connections.
It is up to you to make the necessary effort. When you are struggling to follow the book, do not jump to any conclusions about your own capabilities. You are fine—you just need to keep at it. Take a break, reread some material, and always make sure you read and understand the example programs and exercises. Learning is hard work, but everything you learn is yours and will make subsequent learning easier.
The computer programmer is a creator of universes for which he [sic] alone is responsible. Universes of virtually unlimited complexity can be created in the form of computer programs.
A program is many things. It is a piece of text typed by a programmer, it is the directing force that makes the computer do what it does, it is data in the computer’s memory, yet it controls the actions performed on this same memory. Analogies that try to compare programs to objects we are familiar with tend to fall short. A superficially fitting one is that of a machine—lots of separate parts tend to be involved, and to make the whole thing tick, we have to consider the ways in which these parts interconnect and contribute to the operation of the whole.
A computer is a machine built to act as a host for these immaterial machines. Computers themselves can do only stupidly straightforward things. The reason they are so useful is that they do these things at an incredibly high speed. A program can ingeniously combine an enormous number of these simple actions in order to do very complicated things.
To some of us, writing computer programs is a fascinating game. A program is a building of thought. It is costless to build, it is weightless, and it grows easily under our typing hands.
But without care, a program’s size and complexity will grow out of control, confusing even the person who created it. Keeping programs under control is the main problem of programming. When a program works, it is beautiful. The art of programming is the skill of controlling complexity. The great program is subdued—made simple in its complexity.
Many programmers believe that this complexity is best managed by using only a small set of well-understood techniques in their programs. They have composed strict rules (“best practices”) prescribing the form programs should have, and the more zealous among them will consider those who go outside of this safe little zone to be bad programmers.
What hostility to the richness of programming—to try to reduce it to something straightforward and predictable, to place a taboo on all the weird and beautiful programs! The landscape of programming techniques is enormous, fascinating in its diversity, and still largely unexplored. It is certainly dangerous going, luring the inexperienced programmer into all kinds of confusion, but that only means you should proceed with caution and keep your wits about you. As you learn there will always be new challenges and new territory to explore. Programmers who refuse to keep exploring will stagnate, forget their joy, and get bored with their craft.
Why language matters
In the beginning, at the birth of computing, there were no programming languages. Programs looked something like this:
00110001 00000000 00000000 00110001 00000001 00000001 00110011 00000001 00000010 01010001 00001011 00000010 00100010 00000010 00001000 01000011 00000001 00000000 01000001 00000001 00000001 00010000 00000010 00000000 01100010 00000000 00000000
That is a
program to add the numbers from 1 to 10 together and print out the
1 + 2 + ... + 10 = 55. It could run on a simple,
hypothetical machine. To program early computers, it was necessary to
set large arrays of switches in the right position or punch holes in
strips of cardboard and feed them to the computer. You can probably imagine
how tedious and error-prone this procedure was. Even writing simple
programs required much cleverness and discipline. Complex ones were
Of course, manually entering these arcane patterns of bits (the ones and zeros) did give the programmer a profound sense of being a mighty wizard. And that has to be worth something in terms of job satisfaction.
Each line of the previous program contains a single instruction. It could be written in English like this:
Although that is already more readable than the soup of bits, it is still rather unpleasant. It might help to use names instead of numbers for the instructions and memory locations.
Can you see how the program
works at this point? The first two lines give
two memory locations their starting values:
total will be used to
build up the result of the computation, and
count will keep track of the
number that we are currently looking at. The lines using
probably the weirdest ones. The program wants to see
count is equal to 11 in order to decide whether it can stop
running. Because our hypothetical machine is rather primitive, it can only
test whether a number is zero and make a decision (or jump) based on
that. So it uses the memory location labeled
compare to compute the
count - 11 and makes a decision based on that value. The
next two lines add the value of
count to the result and increment
count by 1 every time the program has decided that
count is not 11 yet.
This version gives us a few more improvements.
Most importantly, there is no need to specify the way we want the
program to jump back and forth anymore. The
construct takes care of that. It continues executing the block
(wrapped in braces) below it as long as the condition it was given
holds. That condition is
count <= 10, which means “
count is less than or equal to
10”. We no longer have to create a temporary value and compare that
to zero, which was an uninteresting detail. Part of the power of
programming languages is that they take care of uninteresting details
At the end of the program, after the
while construct has
console.log operation is applied to the result in
order to write it as output.
Finally, here is what the
program could look like if we happened to have the convenient
sum available, which respectively create a
collection of numbers within a range and compute the sum of a
collection of numbers:
The moral of this story is that the same program can
be expressed in long and short, unreadable and readable ways. The
first version of the program was extremely obscure, whereas this last
one is almost English:
sum of the
range of numbers from
1 to 10. (We will see in later chapters how to
build operations like
programming language helps the programmer by allowing them to talk
about the actions that the computer has to perform on a higher level.
It helps omit uninteresting details, provides convenient building
blocks (such as
console.log), allows you to define your
own building blocks (such as
range), and makes those blocks
easy to compose.
Code, and what to do with it
Code is the text that makes up programs. Most chapters in this book contain quite a lot of it. In my experience, reading code and writing code are indispensable parts of learning to program, so try to not just glance over the examples. Read them attentively and understand them. This may be slow and confusing at first, but I promise that you will quickly get the hang of it. The same goes for the exercises. Don’t assume you understand them until you’ve actually written a working solution.
When reading this book in your browser, you can edit (and run) all example programs by clicking them.
Overview of this book
Throughout the book, there are five project chapters, which describe larger example programs to give you a taste of real programming. In order of appearance, we will work through building an artificial life simulation, a programming language, a platform game, a paint program, and a dynamic website.
The language part of the book starts with four chapters to introduce
(such as the
while word you saw in this introduction),
functions (writing your own
operations), and data structures. After these,
you will be able to write simple programs. Next, Chapters
6 introduce techniques to use functions
and objects to write more abstract code and thus keep complexity
After a first project chapter, the first part of the book continues with chapters on error handling and fixing, on regular expressions (an important tool for working with text data), and on modularity—another weapon against complexity. The second project chapter concludes the first part of the book.
After that, Chapter 20 describes Node.js, and Chapter 21 builds a simple web system using that tool.
In this book, text written in a
font will represent elements of programs—sometimes
they are self-sufficient fragments, and sometimes they just refer to
part of a nearby program. Programs (of which you have already seen a
few), are written as follows:
Sometimes, in order to show the output that a program produces, the expected output is written after it, with two slashes and an arrow in front.