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.

Figure
Programmer

you

System

microwave

Interface

buttons or dials

Program

1:00 time, 50% power

Side Effects
  • turns on when you press start!

  • runs at 50% power for 1:00 minute

  • turns off

Figure
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

Exercise

Fill in the table for the other examples

Exercise

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:

pacmanbot system board
Figure 1. Figure

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?

Exercise

Try to come up with a set of instructions that someone else could use to instruct pacman-bot to move around the board.

Exercise

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)

Exercise

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).

pacmanbot system board

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)

Exercise

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
Exercise

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?

Exercise

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:

a function

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):

function 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}]}

  ...
]
Exercise

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)