What is programming?
“Programming” is the act of creating instructions for a system on what to do or how to behave.
Notice that the above definition mentions nothing about “computers” or “writing code”. “Writing code for computers” happens to be the most common form of programming, but we can learn a lot about programming without throwing “computers” or “code” into the mix.
It’s likely that you’re already a programmer, but you probably don’t realize it. Have you ever:
-
set the microwave to run for 1:00 minute at 50% power?
-
set an alarm clock?
-
texted directions to a friend on how to get someplace?
-
written down a recipe for your special chocolate chip cookies?
If so, then you’ve programmed already.
It’s also likely that you’ve been on the receiving end of a program, that is, you’ve “been programmed” before:
-
built a Lego set according to instructions
-
folded some origami according to instructions
-
played a song from sheet music
-
written a todolist for yourself
Lets break down a few of these situations.
A programmer gets a system to perform side effects by providing a program via an interface.
Programmer |
you |
System |
microwave |
Interface |
buttons or dials |
Program |
1:00 time, 50% power |
Side Effects |
|
Programmer |
you |
System |
your friend |
Interface |
SMS message (freeform english text) |
Program |
ex. Take Hwy 102 south Exit on Fake St. Turn left on Imaginary Blvd. Turn right on Nowhere Rd. House # is 55. |
Side Effects |
friend finds his way to your home |
Fill in the table for the other examples
Come up with a few examples
What vs. How
Our original definition of programming [ref], mentions that the instructions we create while programming describe what a system should do or how it should behave.
The difference between the two is very subtle.
Consider a cookie recipe:
Cookie Recipe:
what:
make some chocolate chip cookies
how:
1. gather the following materials: ...
2. gather the following tools: ...
3. mix together ... in a bowl
4. scoop onto a pan
5. bake in a preheated oven at 450 for 20 minutes
Each of the above steps assumes the reader knows how to perform each of the actions (mix, scoop, etc.).
Notice how each “how” step could be treated as a “what”, and broken down further:
what:
mix together ... in a bowl
how:
1. place empty bowl on counter
2. add ... cups of ... into bowl
3. add ... spoons of ... into bowl
4. ...
5. mix with a wooden spoon
what:
mix with a wooden spoon
how:
1. insert spoon into bowl with ingredients
2. move spoon in a circular motion
3. stop when you can no longer tell ingredients apart
We could keep going deeper and deeper…
| -- / \ /\ /\ /\/\/\/\
In practice, we stop at some point; where we stop depends on what level of instructions we expect the “system” that is processing the instructions to understand.
For our cookie recipe, if you are writing it for a friend who has baked before, (1) is probably sufficient, but for someone who has never stepped inside a kitchen, you may need to go a level or two deeper. If you’re trying to create a cookie making robot, you’d need to get down to the level of “emit a 5V signal on this wire for 0.5s” (to turn on a motor, to move the arm, to pick up the spoon…)
Also notice that the language that is used varies; an experienced cook probably knows what “braising” means, but a beginner would need that explained; a pianist knows what “allegro” means, but most people don’t; these domain-specific terms are used to save time. When you need to explain something, you adapt your language based on what your audience understand. It’s the same with programming - a programmer needs to adapt their language to what the processor (be it a computer or an aspiring chef) can understand.
“levels of abstraction”
We’ve already made a few important observations about programming:
-
programmer
-
systems that process instructions (of various forms)
-
instructions (following various rules, “languages”)
-
instructions can be written at various levels of abstraction a “what” broken down into a number of “how” steps or, a group of “how” steps “abstracted” into a “what”
-
a programmer needs to know what the system understands to be able to create instructions for the system
The last observation is especially important. To program a system, you must know what a system can do and what instructions it understands. Most of programming is learning about various systems that can be programming and then applying that knowledge to make those systems do what you want.
Chapter Title
There are hundreds of different kinds of “computers” (desktops, laptops, tablets, phones, watches, cars, refrigerators), and each is composed of hundreds of interoperating systems. (ref appendix: down the computer rabbit hole) Fortunately, much of what programming entails is transferable between different programmable systems.
In this book, you’ll be learning the basics of “how to program”, or perhaps more accurately, to learn to “think like a programmer”.
What you will be programming, and the language you’ll be programming in doesn’t really matter. But… in order to teach you how to program (in general), this book will also teach you how to program web applications with a real, practical programming language: Clojure [ref: . Why Clojure].
But before we start learning Clojure proper, let’s make a few more observations about systems and instructions using a simple made-up system.
Enter the Pacman
Instructions and Abstraction II
We write programs to solve a certain problem using a certain system. The system we choose contrains us in the way we can program it, and the problem we choose constrains in the way we solve it.
Our program is the mediator between these two domains (the “problem” domain and the “solution” domain) and will often be made of many layers (of abstraction, as we had learned in the previous chapter).
Here is a Pacman-bot system:
Let’s take the role of designers of this system. As the designers, we want to provide other people the ability to program Pacman-bot to move around the board (presumably to get the Cherry and avoid the Ghosts, but who knows what people will come up with). How might we allow people to program Pacman-bot?
Try to come up with a set of instructions that someone else could use to instruct pacman-bot to move around the board.
Test it out on yourself (or a friend) to make sure that Pacman could get from any one place to any other place using the instructions.
Here are a few possible sets:
Set | Instructions | Sample Program |
---|---|---|
A |
forward back left right |
forward forward left forward right |
B |
up down left right (from pacman’s point of view) |
up up down right |
C |
^ v < > |
^>>>>>^>v>>> |
D |
forward rotate-right |
forward rotate-right forward forward rotate-right |
E |
nX eX wX sX (where X is the number of times to repeat the preceding direction) |
n5w2n5 |
F |
(goto! x y) (where x and y are integers corresponding to the row and column, respectively) |
(goto! 1 4) (goto! 1 1) |
G |
(find! object) (where object is one of: cherry or ghost) |
(find! cherry) |
H |
go! (which makes the bot go to the cherry) |
go! |
What we’ve come up with are programming languages! They are very limited, but, yes, they are programming languages. (Now you can tell your friends that not only can you program, but you’ve designed a programming language!)
(Also worth noting: all the examples above are text-based instruction languages, but you could also have come up with visual instruction systems (drawing a map, using colors, using pictograms), a sound-based system, a hand gesture system… anything)
For each language, write down the instructions to get pacman from his starting location to the cherry.
A few things to notice:
-
there’s more than one possible way to define an instruction set for a given system
-
some instruction sets require more explanation (“documentation”) than others
-
some instruction sets are easier than others to solve a problem with
-
some instruction sets result in more instructions than others (but might be easier to solve the problem with)
-
some instruction sets are harder than others to read after the fact (but maybe easier to solve the problem with)
-
given an instruction set, there’s more than one way to solve a problem
-
instruction sets aren’t enough, a language must also define how instructions are to be combined (and as programmers, we must understand not just what instructions are available, but how they can be combined)
Later in this book we will be learning about the Clojure language and all the instructions it supports and how we can combine them to solve problems.
Before we move on from pacman-bot, let’s try the following: can we convert between the different pacman-bot languages? If someone gave us pacman-bot that only understood Language X (v>^<
) could we still program pacman-bot to understand a Language Y program (n5e3w1
)? If v>^<
are the only instructions that Language X allows, then the answer is “no”, at least not directly, but we could write another system that could convert from Language Y to Language X. It might look something like this:
nX means repeat "^" X times wX means repeat "<" X times eX means repeat ">" X times sX means repeat "v" X times
Can you see how the rules above would allow us to convert from n5e3w1
to ^^^^^>>><
?
Now how about converting from Language Z (goto! x y)
to Language Y v>^>
? Ponder that for a moment.
Hmmm…
We have a problem. In order to make pacman-bot follow the (goto! 3 1)
instruction using the v>^<
instructions, we need to know where pacman-bot is before we give him the command. Before, with Language X, we were able to blindly convert from one language to another, but this time, we need some information first (pacman-bot’s starting location).
In our pacmanbot-system, pacmanbot’s location is at (x,y) = (3,4)
.
Lets refer to pacman bot’s starting location as pacmanX and pacmanY (so, for figure1 we would say that pacmanX is 3 and pacmanY is 4).
Now, back to our problem: how do we go from an instruction like (goto! 3 1)
to v>^<
style instructions? (knowing that pacman-bot starts at pacmanX
and pacmanY
)
Try to come up with some rules to make the conversion possible. Use any words you want. It might take a little more math this time.
One way we could write down the rules could be:
given pacmanX is some number indicating pacman-bot's starting X position given pacmanY is some number indicating pacman-bot's starting Y position (goto! targetX targetY) means: if targetX is greater than pacmanX: repeat ">" (targetX - pacmanX) times if targetX is less than pacmanX: repeat "<" (pacmanX - targetX) times if targetY is greater than pacmanY: repeat "v" (targetY - pacmanY) times if targetY is less than pacmanY: repeat "^" (pacmanY - targetY) times
Follow the rules above to convert from (goto! 3 1)
to v>^<
instructions, given that pacman-bot starts at his location in Figure 1: [3, 4].
Got it? Now, follow the v>^<
instructions to make sure our conversion did things correctly. Does it work?
Our goto!
command depends on pacman-bot’s initial position (pacmanX
and pacmanY
), which we could also say is pacman-bots “initial state”.
The command also needs to be given the targetX
and targetY
, which are pacman-bot’s final target position (or “end state”). We can think of our goto!
command as “taking pacman-bot from some initial state to some target state.”
What if we wanted to implement Language Z now (find! object)
?
First off… we need some extra information. Whereas before, we were given the location to go to as part of the instructions, ex. (goto! 3 1)
, now we will be given an object, either the cherry or the ghost, so we will need to know their locations. Lets call the cherry’s location cherryX
and cherryY
, and the ghost’s location ghostX
and ghostY
.
We could implement the (find! object)
command as follows:
pacmanX, pacmanY, cherryX, cherryY, ghostX, ghostY are the X Y position of pacman, cherry and ghost (find! object) means: if object is cherry: if cherryX is greater than pacmanX: repeat ">" (cherryX - pacmanX) times if cherryX is less than pacmanX: repeat "<" (pacmanX - cherryX) times if cherryY is greater than pacmanY: repeat "v" (cherryY - pacmanY) times if cherryY is less than pacmanY: repeat "^" (pacmanY - cherryY) times if object is ghost: if ghostX is greater than pacmanX: repeat ">" (ghostX - pacmanX) times if ghostX is less than pacmanX: repeat "<" (pacmanX - ghostX) times if ghostY is greater than pacmanY: repeat "v" (ghostY - pacmanY) times if ghostY is less than pacmanY: repeat "^" (pacmanY - ghostY) times
Our instructions here are very similar to what we had before with (goto! x y)
. They’re also very repetitive.
What if we could just use (goto! x y)
inside of our (find! object)
command? What might that look like?
Try to rewrite our find!
command using goto!
.
Here’s what we might end up with:
given we have pacmanX, pacmanY, cherryX, cherryY, ghostX, ghostY as defined before given we have `goto!` as defined before (find! object) means: if object is cherry: (goto! cherryX cherryY) if object is ghost: (goto! ghostX ghostY)
Bam! That’s all we need. Ponder it for a moment.
What we’ve done is pretty impressive. We’ve written rules so we can convert from (find! object)
to (goto! x y)
to v>^<
style instructions.
Another way to think about it, is that we’ve written instructions at “different levels of abstractions” (from chapter 1, remember?)
find! | goto! / | | \ v > ^ <
Later, we’ll learn that the find!
and goto!
commands we defined would typically be called “functions”. v
, >
, ^
and <
could also be called “functions”, except in our examples, v>^<
were provided to us by the pacman-bot system, while find!
and goto!
we created ourselves.
Defining “functions” that call other “functions” (…that call other “functions”, that call other “functions”…) is one of the primary activites of “real world” programming.
Functions
One thing to notice about the functions we made up in the previous chapter is that some of them require some information to be passed in, while others could be written on their own (for example, goto
needed an X
and Y
, while v
did not). We can think of those values as “inputs” to the functions (later we’ll also hear them called “parameters”, but for now, lets stick to “inputs”).
With our pacman-bot system, we had an initial state (the positions of pacman-bot, the cherry and the ghost) and our goto!
and find!
function would change (or “transition”) the state into a new state by moving pacman-bot to a new location.
State of Pacman-bot System |
Example |
position of pacman |
(3,4) |
position of ghost |
(3,2) |
position of cherry |
(3,1) |
Pick your favorite board game or card game. What information do you need to describe the entire state?
We can say that our goto!
and find!
functions have “side effects” (ie. running them causes a change in the state of the system)
Can we have functions without “side effects”? Would that ever be useful in a language?
What if… we had functions, which, instead of changing the system state, could just “return” the value of some calculation. For example:
(subtract x y) means: return the result of subtracting y from x (ie. x - y)
If we were to write (subtract 5 2)
it would “return” 3
.
If we defined:
(divide x y) means: return the result of dividing x and y (ie. x / y)
Then, (divide 15 5)
would “return” 3
.
We can think of the “return” values of a function as the “output” of the function.
Could we maybe allow for the output of a function to be used as an input? Perhaps we could write something like this:
(divide 21 (subtract 8 1))
…which we would say “returns” 3
because: (subtract 8 1)
returns 7
, and (divide 21 7)
returns 3
.
This is getting interesting.
Perhaps we could write a function that combines our divide
and subtract
functions?
How about a function to calculate the slope of a line:
(slope x1 y1 x2 y2) means: return the result of: (divide (subtract y2 y1) (subtract x2 x1))
Instead of changing the state of some surrounding system, our divide
, subtract
and slope
functions are just “returning” values. What’s the use of these “returned values”? To use as “inputs” to other functions!
Presumably, at some point, we would want some side effects (say, like, printing out the result of a calculation to the screen), but, we could probably get a lot done just with functions that don’t change state.
(Read this later: Appendix X: Avoiding State)
In the future, we will refer to functions that don’t change state as “pure” functions, and ones that do as “stateful” or “impure” functions.
Title
We can now think of functions as a type of instructions that a system understands, which optionally take some inputs, optionally return some values, and optionally change some state:
There are some functions that a system provides for us (like v>^<
from our pacman-bot example) and others that we write ourselves, using the system functions, to make our lives easier (like goto!
and slope
).
We can now think of a “program” as a function of functions (…of functions …of functions):
Like the functions inside of it, the “program” function may take some input, change state, and return some output.
For example, a simple program could take in a number and two currencies and return you the result of converting from one currency to another based on today’s exchange rate. A more complicated program might take some input (say, mouse clicks and keyboard button presses) and change the display of the screen to let you play a game.
We’re almost ready to starting learning Clojure proper, we just have one more concept to cover: “data”.
Data
Let’s think back to our find!
“program”/“function” that we wrote for the pacman-bot system.
(find! object) means:
if object is cherry:
(goto! cherryX cherryY)
if object is ghost:
(goto! ghostX ghostY)
find!
would take an object as input (cherry or ghost) and change the state of the pacman-bot system so that pacman-bot would end up in the same position as the specified object. It would make use of the v><^
functions, which were provided by the system. It also needed to know the positions of pacman-bot, the cherry and the ghost (which were provided by the system as pacmanX
, cherryX
, ghostX
…)
The input object and the positions pacman-bot, the cherry and the ghost were all pieces of information that our find!
program needed to function. We refer to these kinds of pieces of information, in a broad sense, as “data”.
Real world programs deal with a lot of data — lists of friends, blog posts, photos, addresses of businesses — and as a programmer, much of what you will be doing is transforming, combining, seperating and recombining data (using functions!).
In our programs, data will be used in various ways:
-
as inputs into our program (ex. a stream of Twitter updates), so that we can write one program and use it with different sets of data
-
passed into functions and returned from functions
-
to represent the state of the system (ex. the positions of the objects in our pacman-bot system)
-
as a “hardcoded” reference to help our programs do what they need to do (for example, a table to from months-of-the-year in english to their numerical equivalents)
There are infinite kinds of data we might want to handle in a program, but, it turns out, we can represent almost any kind of information using a few simple building blocks:
Primitive Values
Primitive values are the simplest forms of data; you can think of them as the atoms of the programming world. They include numbers (such as 1
and 1.5
), “strings” (which represent text, such as "hello"
and "goodbye"
) and other types of things called “booleans”, “keywords” and “nil”. Let’s take a look at each.
Numbers
A “number” is a numerical values. Clojure, which is the language we’ll be using for the rest of this book understands three kinds of numbers:
Integers (ex. 25
)
Decimals (ex. 23.234
) (also called “doubles”, “floats”, and “longs” in some languages)
Fractions (ex. 7/23
)
From now on, we’ll refer to all three of these forms as “numbers”.
Strings
A “string” represents text. It can be a single character: "a"
, a word: "elephant"
, a sentence: "This is a string"
, or the entire corpus of Shakespeare’s works: (uhhh… to save space, we’ll skip the example for this one).
In Clojure, as in most programming languages, strings are written with quotation marks around them, like so: "hello again!"
. The quotation marks are necessary to help differentiate strings from names of functions in our program (so, goto!
would be the function, while "goto!"
would just be the text). In a similar vein, 2
is the number 2, while "2"
is a string - they are completely different things, as far as Clojure is concerned.
Booleans
A “boolean” is a fancy programmer term for the concepts of “true” and “false”. In Clojure, that’s exactly how we write them: true
and false
. They come in handy for representing certain information (ex. is John late? → true
), as results of comparisons (ex. is 3 greater than 5? → false
) and as return values from functions (ex. (even? 5)
→ false
).
Just to make it super clear, true
is not the same things as "true"
(the first is a boolean, the second is a string).
nil
“nil” is a special value that represents the “lack of a value” or “nothingness”. In math, that honor is usually bestowed to 0
, but because 0
is already number, it ends up being very useful to have a way to say “nothing”. In Clojure, you can write it simply as nil
.
keywords
A “keyword” is a label that is used in our programs to help us name things (we’ll see them very soon in maps). For example, we might have a program that deals with colors, which we could represent in Clojure with keywords as so: :red
, :white
, :green
, :purple
. Keywords start with a colon (:
).
Keywords might seem similar to strings (and in some languages, there are no keywords), but they’re not meant to be “broken down” like strings; with a string, we might ask for the 10th character, or count the number of characters, or count the number of words, or split a string into seperate words — these operations can’t be done with keywords. Strings can be thought of as a “collection of characters” while keywords are just a handy label to use in our programs.
If the distinction is confusing, don’t worry about it. If you use strings instead of keywords, your programs will still work.
compound values
Primitive values are nice, but we often need to deal with collections of values, and that’s where “vectors” and “maps” come in. If primitive values were the atoms of the programming world, then “compound values” are the molecules.
vectors
A “vector” is an ordered lists of values. In Clojure, we represent a vector by listing values in between square brackets ([]
). For example, here is a vector of numbers: [10 4 2 6]
, and here is a vector of strings and numbers: [1 "hello" 4 "goodbye"]
.
In other languages, you may also hear vectors referred to as “lists”, “arrays” or “sequences”.
Being able to store values in lists ends up being very, very useful. Vectors will also allow us to add values to them, remove values, do something for each value inside, and retrieve values based on their position.
Vectors can also contain non-primitive values, such as other vectors: [1 2 3 ["four" [:five]]]
maps
A “maps” is like a real-world dictionary; it contains a list of “keys”, each of which correponds to a certain “value”. In a real-world dictionary, the “keys” are the words and the “values” are the definitions.
Here is an example of an (abridged) real-world dictionary in Clojure, written as a map of strings to strings:
{ "Chair" "A piece of furniture used for sitting." "Orange" "A citrus fruit or color." "Guitar" "A musical instrument." }
Just as with a real-world dictionary, we can lookup the corresponding definition (“value”) to a word (“key”). We could do this by writing: (dictionary "chair")
which would return "A piece of furniture used for sitting"
.
Maps end up being useful for representing lots of different real world data, such as people: { :name "Bob" :age 23 }
or places: { :name "Ghost Town" :population 0 }
Maps can have any values as “keys” and any values as “values”. This is a totally legitimate map:
{ [1 2] "one two" :three "three" {} nil }
other types
There are more types in Clojure than mentioned here, but these ones will do for now, and we’ll see the others in the future (notably: “sets”, “datetimes” and “uuids”).
putting things together
Now that we know various kinds of values that we can work with, let’s represent some non-trivial data using them.
How might we represent the countries of the world, their areas, populations and capital cities?
Here’s one way:
[ { :name "Canada" :population 1234 :area 4567 :capital "Toronto" :cities [{:name "Toronto" :area 456 :population 1252} {:name "Montreal" :area 512 :population 1262}]} { :name "China" :population 2345 :area 5678 :capital "Beijing" :cities [{:name "Beijing" :area 123 :population 1235} {:name "Shanghai" :area 456 :population 542}]} ... ]
Try coming up with ways of representing the following data sets:
-
a contact list (each with names, an email and multiple phone numbers)
-
the pacman-bot system
-
the system you came up with in <previous chapter exercise>
-
a count of how many times each letter occurs in a piece of text
Derived Values
-
a shopping receipt
Transformations
Constants |
State |
Helper Functions |
Actions |
Enter Clojure
It’s now time to being learning Clojure proper.
As we had discussed in Chp 1, a programming language consists of two broad concepts: - the various commands that you can call - the rules of how to write and combine the commands (the "syntax")
In this chapter, we will learn a few Clojure commands, but focus mostly on how commands are written and how they can be combined. We’ll then start using Clojure to solve simple problems. Over the next few chapters we will gradually introduce more and more of the functions that Clojure has built-in and use them to solve increasingly difficult problems.
Clojure Syntax
A Clojure program is written as text and is composed of "values", "forms", and "symbols". The text that is
"Values" are text that represents data. We spent all of the previous chapter discussing values. Here’s a number: 1
, a string: "hello!"
, and vector of numbers: [1 2 3]
Symbols are text that are used to name things and refer to things that have been named. For example, we could give the vector ["Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"]
the name days-of-the-week
and later refer to it as days-of-the-week
instead of writing it all out again (we’ll cover this in more detail very soon).
A "form" is unit of code that contains values, forms and/or symbols. It is a set of brackets surrounding some content.
Here is any empty "form": ()
.
Here is a form with 3 numbers: (1 2 3)
Here is a form with 2 numbers and a vector of numbers: (1 2 [3 4])
Here are two forms, one after the other: ("a" "b" "c") (1 2 3)
Here is a form within a form: (1 (2) 3)
Here is a form with a 2 symbols and a string (println "Hello" name)
A Clojure "program" is a text file that contains one or more forms, values or symbols. Each form can contain one or more forms, values or symbols.
…and that’s it for the syntax.
Clojure Functions
In Chapter 1, we discussed how languages define a set of commands that the programmer can call, and if the syntax allows for it, a way to create our own commands (which we called "functions") that are named combinations of the provided commands and/or our own commands.
To start, we will learn X of Clojure’s built-in "commands":
print
(print "Happy Monday "Bob!")
let
(let [name "Bob"]
...
)
fn
+
/
if when
map
(let [blah (fn [] )]
)
Solving Problems
identify: inputs outputs other required information
any steps
start 'top-down'
making up names of functions
do what you know
test
don't worry about perfect: make things work, then make things right
Morse Code
print def defn ->> split map join
(defn str→vec [s] (clojure.string/split s ""))
(defn vec→str [v] (clojure.string/join "" v))
(def lookup {"s" "…" "o" "---"})
(defn char→morse [char] (get lookup char))
(defn text→morse [text] (→> text str→vec (map char→morse) vec→str))
(text→morse "hello world")
Merge Sort
(defn merge [coll-a coll-b]
)
(defn merge-sort [coll]
(if (<= (count coll) 2)
coll
(let [[a b] (split-at (/ (count coll) 2) coll)]
(concat (merge-sort a) (merge-sort b)))))
Character Frequency
Average
reduce (or apply)
Web Development
Understanding the systems we’ll be using: - browser - HTML - CSS - JS - HTTP
react reagent
Appendix A: Programming Interfaces
text by far most popular piggyback on our ability to read
decent density ratio easy to manipulate
flow-based
block-based (scratch)
cell-based (excel)
…
Appendix B: Why Clojure
LISP = less syntax:
just (fn arg arg)
+ some data types
no semicolons, no commas
ie. more time learning functions and "thinking like a progammer"; less on fighting compiler
REPL
practical
reach
Appendix C: Down the Computer Rabbit Hole
your program … clojure … java … OS? … assembly (bytecode?) binary CPU … adders, latches, … AND, OR, NAND gates electrons and PNP transistors
Appendix D: Programming Exercises
password obfuscator given a string replace each occurence handle uppercae and lowercase a → 4 e → 3 o → 0 l → 1
bound count words in a file count occurence of each character in a file identify if a word is a palindrome merge sort identify duplicate files in a directory translate from piglatin and back english to morse code and back
encrypt and decrypt some text
tally up voting results
english numbers → integers and back
body mass index
credit card number checker (luhn)
levenstein distance
fuzzy search (using lev)
guess my number game ("smaller" / "larger") choose your own adventure game schedule fitter (simulated annealing) accounting system sudoku solver mastermind game (w/ cheating ai) implement the pacman-bot system
game of life
xor, nor, and, or
Appendix E: Avoiding State
what is state
why state is bad
how we can avoid state
Appendix F: Text Encoding
Appendix G: Regular Expressions
Appendix H: Clojure Style Guide
Appendix I: Clojure Cheatsheet
Appendix J: Debugging
Appendix K: Refactoring
Appendix L: Test Driven Development
Appendix M: Choosing an Editor
Lightable + plugins
Cursive
Atom + plugins
Emacs
Vi
Appendix N: Resources
Clojure Brave and True
Cognitory
clojuredocs
Appendix O: Glossary
- Code (v)
- Code (n)
- Program (n)
- Program (v)
- Programming (n)
- Function (n)
- Function (v)
- String (n)
- Comment (n)
- Test (n)
- Test (v)
- Test Driven Development (n)
- Parameter (n)
- Abstract (v)
- Side Effect (n)
- Return (v)
- Returned Value (n)
- Input (n)
- Output (n)
- Pure Function (n)
- Data (n)
- Boolean (n)
- Nil (n)
- Map (n)
- Map (v)