https://github.com/ligurio/clojure-from-the-ground-up
Book about Clojure written by Kyle Kingsbury https://aphyr.com/tags/Clojure-from-the-ground-up, formatting and conversion to Markdown, EPUB and HTML by Sergey Bronnikov.
https://github.com/ligurio/clojure-from-the-ground-up
book clojure programming programming-language
Last synced: 12 months ago
JSON representation
Book about Clojure written by Kyle Kingsbury https://aphyr.com/tags/Clojure-from-the-ground-up, formatting and conversion to Markdown, EPUB and HTML by Sergey Bronnikov.
- Host: GitHub
- URL: https://github.com/ligurio/clojure-from-the-ground-up
- Owner: ligurio
- Created: 2020-07-30T08:44:19.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2024-05-08T14:58:41.000Z (about 2 years ago)
- Last Synced: 2025-03-23T18:54:21.872Z (about 1 year ago)
- Topics: book, clojure, programming, programming-language
- Language: Makefile
- Homepage: https://bronevichok.ru/static/Kyle_Kingsbury_Clojure_From_The_Ground_Up.html
- Size: 554 KB
- Stars: 21
- Watchers: 3
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Clojure from the ground up
## Welcome
This guide aims to introduce newcomers and experienced programmers alike to the
beauty of functional programming, starting with the simplest building blocks of
software. You’ll need a computer, basic proficiency in the command line, a text
editor, and an internet connection. By the end of this series, you’ll have a
thorough command of the Clojure programming language.
### Who is this guide for?
Science, technology, engineering, and mathematics are deeply rewarding fields,
yet few women enter STEM as a career path. Still more are discouraged by a
culture which repeatedly asserts that women lack the analytic aptitude for
writing software, that they are not driven enough to be successful scientists,
that it’s not cool to pursue a passion for structural engineering. Those few
with the talent, encouragement, and persistence to break in to science and tech
are discouraged by persistent sexism in practice: the old boy’s club of tenure,
being passed over for promotions, isolation from peers, and flat-out assault.
This landscape sucks. I want to help change it.
Women Who Code, PyLadies, Black Girls Code, RailsBridge, Girls Who Code, Girl
Develop It, and Lambda Ladies are just a few of the fantastic groups helping
women enter and thrive in software. I wholeheartedly support these efforts.
In addition, I want to help in my little corner of the technical
community–functional programming and distributed systems–by making high-quality
educational resources available for free. The
[Jepsen](https://aphyr.com/tags/jepsen) series has been, in part, an effort to
share my enthusiasm for distributed systems with beginners of all stripes–but
especially for women, LGBT folks, and people of color.
As technical authors, we often assume that our readers are white, that our
readers are straight, that our readers are traditionally male. This is the
invisible default in US culture, and it’s especially true in tech. People
continue to assume on the basis of my software and writing that I’m straight,
because well hey, it’s a statistically reasonable assumption.
But I’m not straight. I get called faggot, cocksucker, and sinner. People say
they’ll pray for me. When I walk hand-in-hand with my boyfriend, people roll
down their car windows and stare. They threaten to beat me up or kill me. Every
day I’m aware that I’m the only gay person some people know, and that I can
show that not all gay people are effeminate, or hypermasculine, or ditzy, or
obsessed with image. That you can be a manicurist or a mathematician or both.
Being different, being a stranger in your culture, comes with all kinds of
challenges. I can’t speak to everyone’s experience, but I can take a pretty
good guess.
At the same time, in the technical community I’ve found overwhelming warmth and
support, from people of all stripes. My peers stand up for me every day, and
I’m so thankful–especially you straight dudes–for understanding a bit of what
it’s like to be different. I want to extend that same understanding, that same
empathy, to people unlike myself. Moreover, I want to reassure everyone that
though they may feel different, they do have a place in this community.
So before we begin, I want to reinforce that you can program, that you can do
math, that you can design car suspensions and fire suppression systems and
spacecraft control software and distributed databases, regardless of what your
classmates and media and even fellow engineers think. You don’t have to be
white, you don’t have to be straight, you don’t have to be a man. You can grow
up never having touched a computer and still become a skilled programmer. Yeah,
it’s harder–and yeah, people will give you shit, but that’s not your fault and
has nothing to do with your ability or your right to do what you love. All it
takes to be a good engineer, scientist, or mathematician is your curiosity,
your passion, the right teaching material, and putting in the hours.
There’s nothing in this guide that’s just for lesbian grandmas or just for
mixed-race kids; bros, you’re welcome here too. There’s nothing dumbed down.
We’re gonna go as deep into the ideas of programming as I know how to go, and
we’re gonna do it with everyone on board.
No matter who you are or who people think you are, this guide is for you.
### Why Clojure?
This book is about how to program. We’ll be learning in Clojure, which is a
modern dialect of a very old family of computer languages, called Lisp. You’ll
find that many of this book’s ideas will translate readily to other languages;
though they may be [expressed in different
ways](http://aphyr.com/posts/266-core-language-concepts).
We’re going to explore the nature of syntax, metalanguages, values, references,
mutation, control flow, and concurrency. Many languages leave these ideas
implicit in the language construction, or don’t have a concept of metalanguages
or concurrency at all. Clojure makes these ideas explicit, first-class language
constructs.
At the same time, we’re going to defer or omit any serious discussion of static
type analysis, hardware, and performance. This is not to say that these ideas
aren’t important; just that they don’t fit well within this particular
narrative arc. For a deep exploration of type theory I recommend a study in
Haskell, and for a better understanding of underlying hardware, learning C and
an assembly language will undoubtedly help.
In more general terms, Clojure is a well-rounded language. It offers broad
library support and runs on multiple operating systems. Clojure performance is
not terrific, but is orders of magnitude faster than Ruby, Python, or
Javascript. Unlike some faster languages, Clojure emphasizes safety in its type
system and approach to parallelism, making it easier to write correct
multithreaded programs. Clojure is concise, requiring very little code to
express complex operations. It offers a REPL and dynamic type system: ideal for
beginners to experiment with, and well-suited for manipulating complex data
structures. A consistently designed standard library and full-featured set of
core datatypes rounds out the Clojure toolbox.
Finally, there are some drawbacks. As a compiled language, Clojure is much
slower to start than a scripting language; this makes it unsuitable for writing
small scripts for interactive use. Clojure is also not well-suited for
high-performance numeric operations. Though it is possible, you have to jump
through hoops to achieve performance comparable with Java. I’ll do my best to
call out these constraints and shortcomings as we proceed through the text.
With that context out of the way, let’s get started by installing Clojure!
### Getting set up
First, you’ll need a Java Virtual Machine, or JVM, and its associated
development tools, called the JDK. This is the software which runs a Clojure
program. If you’re on Windows, install [Oracle JDK
1.7](http://www.oracle.com/technetwork/java/javase/downloads/index.html). If
you’re on OS X or Linux, you may already have a JDK installed. In a terminal,
try:
```clojure
which javac
```
If you see something like
```clojure
/usr/bin/javac
```
Then you’re good to go. If you don’t see any output from that command, install
the appropriate [Oracle JDK
1.7](http://www.oracle.com/technetwork/java/javase/downloads/index.html) for
your operating system, or whatever JDK your package manager has available.
When you have a JDK, you’ll need [Leiningen](http://leiningen.org/), the
Clojure build tool. If you’re on a Linux or OS X computer, the instructions
below should get you going right away. If you’re on Windows, see the Leiningen
page for an installer. If you get stuck, you might want to start with a [primer
on command line basics](http://blog.teamtreehouse.com/command-line-basics).
```shell
mkdir -p ~/bin
cd ~/bin
curl -O https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
chmod a+x lein
```
Leiningen automatically handles installing Clojure, finding libraries from the
internet, and building and running your programs. We’ll create a new Leiningen
project to play around in:
```shell
cd
lein new scratch
```
This creates a new directory in your homedir, called `scratch`. If you see
`command not found` instead, it means the directory `~/bin` isn’t registered with
your terminal as a place to search for programs. To fix this, add the line
```shell
export PATH="$PATH":~/bin
```
to the file `.bash_profile` in your home directory, then run `source
~/.bash_profile`. Re-running `lein new scratch` should work.
Let’s enter that directory, and start using Clojure itself:
```shell
cd scratch
lein repl
```
### The structure of programs
When you type `lein repl` at the terminal, you’ll see something like this:
```shell
aphyr@waterhouse:~/scratch$ lein repl
nREPL server started on port 45413
REPL-y 0.2.0
Clojure 1.5.1
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
user=>
```
This is an interactive Clojure environment called a REPL, for “Read, Evaluate,
Print Loop”. It’s going to read a program we enter, run that program, and print
the results. REPLs give you quick feedback, so they’re a great way to explore a
program interactively, run tests, and prototype new ideas.
Let’s write a simple program. The simplest, in fact. Type “nil”, and hit enter.
```clojure
user=> nil
nil
```
`nil` is the most basic value in Clojure. It represents emptiness, nothing-doing,
not-a-thing. The absence of information.
```clojure
user=> true
true
user=> false
false
```
`true` and `false` are a pair of special values called Booleans. They mean exactly
what you think: whether a statement is true or false. `true`, `false`, and `nil` form
the three poles of the Lisp logical system.
```clojure
user=> 0
0
```
This is the number zero. Its numeric friends are `1`, `-47`, `1.2e-4`, `1/3`, and so
on. We might also talk about *strings*, which are chunks of text surrounded by
double quotes:
```clojure
user=> "hi there!"
"hi there!"
```
`nil`, `true`, `0`, and `"hi there!"` are all different types of *values*; the nouns of
programming. Just as one could say “House.” in English, we can write a program
like `"hello, world"` and it evaluates to itself: the string `"hello world"`. But
most sentences aren’t just about stating the existence of a thing; they involve
*action*. We need *verbs*.
```
user=> inc
#
```
This is a verb called `inc`–short for “increment”. Specifically, `inc` is a
*symbol* which points to a verb: `#` – just like
the word “run” is a *name* for the *concept* of running.
There’s a key distinction here–that a signifier, a reference, a label, is not
the same as the signified, the referent, the concept itself. If you write the
word “run” on paper, the ink means nothing by itself. It’s just a symbol. But
in the mind of a reader, that symbol takes on *meaning*; the idea of running.
Unlike the number 0, or the string “hi”, symbols are references to other
values. when Clojure evaluates a symbol, it looks up that symbol’s meaning.
Look up `inc`, and you get `#`.
Can we refer to the symbol itself, *without* looking up its meaning?
```clojure
user=> 'inc
inc
```
Yes. The single quote `'` escapes a sentence. In programming languages, we call
sentences `expressions` or statements. A quote says “Rather than *evaluating* this
expression’s text, simply return the text itself, unchanged.” Quote a symbol,
get a symbol. Quote a number, get a number. Quote anything, and get it back
exactly as it came in.
```clojure
user=> '123
123
user=> '"foo"
"foo"
user=> '(1 2 3)
(1 2 3)
```
A new kind of value, surrounded by parentheses: the *list*. LISP originally stood
for LISt Processing, and lists are still at the core of the language. In fact,
they form the most basic way to compose expressions, or sentences. A list is a
single expression which has *multiple parts*. For instance, this list contains
three elements: the numbers 1, 2, and 3. Lists can contain anything: numbers,
strings, even other lists:
```clojure
user=> '(nil "hi")
(nil "hi")
```
A list containing two elements: the number 1, and a second list. That list
contains two elements: the number 2, and another list. *That* list contains two
elements: 3, and an empty list.
```clojure
user=> '(1 (2 (3 ())))
(1 (2 (3 ())))
```
You could think of this structure as a tree–which is a provocative idea,
because *languages* are like trees too: sentences are comprised of clauses, which
can be nested, and each clause may have subjects modified by adjectives, and
verbs modified by adverbs, and so on. “Lindsay, my best friend, took the dog
which we found together at the pound on fourth street, for a walk with her
mother Michelle.”
```clojure
Took
Lindsay
my best friend
the dog
which we found together
at the pound
on fourth street
for a walk
with her mother
Michelle
```
But let’s try something simpler. Something we know how to talk about.
“Increment the number zero.” As a tree:
```clojure
Increment
the number zero
```
We have a symbol for incrementing, and we know how to write the number zero.
Let’s combine them in a list:
```clojure
clj=> '(inc 0)
(inc 0)
```
A basic sentence. Remember, since it’s quoted, we’re talking about the tree,
the text, the expression, by itself. Absent interpretation. If we remove the
single-quote, Clojure will *interpret* the expression:
```clojure
user=> (inc 0)
1
```
Incrementing zero yields one. And if we wanted to increment *that* value?
```clojure
Increment
increment
the number zero
user=> (inc (inc 0))
2
```
A sentence in Lisp is a list. It starts with a verb, and is followed by zero or
more objects for that verb to act on. Each part of the list can *itself* be
another list, in which case that nested list is evaluated first, just like a
nested clause in a sentence. When we type
```clojure
(inc (inc 0))
```
Clojure first looks up the meanings for the symbols in the code:
```clojure
(#
(#
0))
```
Then evaluates the innermost list (`inc 0`), which becomes the number 1:
```clojure
(#
1)
```
Finally, it evaluates the outer list, incrementing the number 1:
```clojure
2
```
Every list starts with a verb. Parts of a list are evaluated from left to
right. Innermost lists are evaluated before outer lists.
```clojure
(+ 1 (- 5 2) (+ 3 4))
(+ 1 3 (+ 3 4))
(+ 1 3 7)
11
```
That’s it.
The entire grammar of Lisp: the structure for every expression in the language.
We transform expressions by *substituting* meanings for symbols, and obtain
some result. This is the core of the [Lambda
Calculus](http://en.wikipedia.org/wiki/Lambda_calculus), and it is the
theoretical basis for almost all computer languages. Ruby, Javascript, C,
Haskell; all languages express the text of their programs in different ways,
but internally all construct a tree of expressions. Lisp simply makes it
explicit.
### Review
We started by learning a few basic nouns: numbers like `5`, strings like `"cat"`,
and symbols like `inc` and `+`. We saw how quoting makes the difference between an
*expression* itself and the thing it *evaluates* to. We discovered symbols as *names*
for other values, just like how words represent concepts in any other language.
Finally, we combined lists to make trees, and used those trees to represent a
program.
With these basic elements of syntax in place, it’s time to expand our
vocabulary with new verbs and nouns; learning to represent more complex values
and transform them in different ways.
## Basic types
We’ve learned the basics of Clojure’s syntax and evaluation model. Now we’ll
take a tour of the basic nouns in the language.
### Types
We’ve seen a few different values already – for instance, `nil`, `true`, `false`, `1`,
`2.34`, and `"meow"`. Clearly all these things are *different* values, but some of
them seem more alike than others.
For instance, `1` and `2` are *very* similar numbers; both can be added, divided,
multiplied, and subtracted. `2.34` is also a number, and acts very much like 1
and 2, but it’s not quite the same. It’s got *decimal* points. It’s not an
*integer*. And clearly `true` is *not very* much like a number. What is true plus
one? Or false divided by 5.3? These questions are poorly defined.
We say that a *type* is a group of values which work in the same way. It’s a
*property* that some values share, which allows us to organize the world into
sets of similar things. 1 + 1 and 1 + 2 use the *same addition*, which adds
together integers. Types also help us *verify* that a program makes sense: that
you can only add together numbers, instead of adding numbers to porcupines.
Types can overlap and intersect each other. Cats are animals, and cats are
fuzzy too. You could say that a cat is a *member* (or sometimes “instance”), of
the fuzzy and animal types. But there are fuzzy things like moss which *aren’t*
animals, and animals like alligators that aren’t fuzzy in the slightest.
Other types completely subsume one another. All tabbies are housecats, and all
housecats are felidae, and all felidae are animals. Everything which is true of
an animal is automatically true of a housecat. Hierarchical types make it
easier to write programs which don’t need to know all the specifics of every
value; and conversely, to create new types in terms of others. But they can
also get in the way of the programmer, because not every useful classification
(like “fuzziness”) is purely hierarchical. Expressing overlapping types in a
hierarchy can be tricky.
Every language has a *type system*; a particular way of organizing nouns into
types, figuring out which verbs make sense on which types, and relating types
to one another. Some languages are strict, and others more relaxed. Some
emphasize hierarchy, and others a more ad-hoc view of the world. We call
Clojure’s type system *strong* in that operations on improper types are simply
not allowed: the program will explode if asked to subtract a dandelion. We also
say that Clojure’s types are *dynamic* because they are enforced when the program
is run, instead of when the program is first read by the computer.
We’ll learn more about the formal relationships between types later, but for
now, keep this in the back of your head. It’ll start to hook in to other
concepts later.
### Integers
Let’s find the type of the number 3:
```clojure
user=> (type 3)
java.lang.Long
```
So 3 is a `java.lang.Long`, or a “Long”, for short. Because Clojure is built on
top of Java, many of its types are plain old Java types.
Longs, internally, are represented as a group of sixty-four binary digits (ones
and zeroes), written down in a particular pattern called [signed two’s
complement representation](http://en.wikipedia.org/wiki/Two's_complement). You
don’t need to worry about the specifics–there are only two things to remember
about longs. First, longs use one bit to store the sign: whether the number is
positive or negative. Second, the other 63 bits represent the *size* of the
number. That means the biggest number you can represent with a long is 2^63 - 1
(the minus one is because of the number 0), and the smallest long is -2^63.
How big is 2^63 - 1?
```clojure
user=> Long/MAX_VALUE
9223372036854775807
```
That’s a reasonably big number. Most of the time, you won’t need anything
bigger, but… what if you did? What happens if you add one to the biggest Long?
```clojure
user=> (inc Long/MAX_VALUE)
ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)
```
An error occurs! This is Clojure telling us that something went wrong. The type
of error was an `ArithmeticException`, and its message was “integer overflow”,
meaning “this type of number can’t hold a number that big”. The error came from
a specific *place* in the source code of the program: `Numbers.java`, on line 1388.
That’s a part of the Clojure source code. Later, we’ll learn more about how to
unravel error messages and find out what went wrong.
The important thing is that Clojure’s type system *protected* us from doing
something dangerous; instead of returning a corrupt value, it aborted
evaluation and returned an error.
If you do need to talk about really big numbers, you can use a BigInt: an
arbitrary-precision integer. Let’s convert the biggest Long into a BigInt, then
increment it:
```clojure
user=> (inc (bigint Long/MAX_VALUE))
9223372036854775808N
```
Notice the N at the end? That’s how Clojure writes arbitrary-precision integers.
```clojure
user=> (type 5N)
clojure.lang.BigInt
```
There are also smaller numbers.
```clojure
user=> (type (int 0))
java.lang.Integer
user=> (type (short 0))
java.lang.Short
user=> (type (byte 0))
java.lang.Byte
```
Integers are half the size of Longs; they store values in 32 bits. Shorts are
16 bits, and Bytes are 8. That means their biggest values are 2^31-1, 2^15-1, and
2^7-1, respectively.
```clojure
user=> Integer/MAX_VALUE
2147483647
user=> Short/MAX_VALUE
32767
user=> Byte/MAX_VALUE
127
```
### Fractional numbers
To represent numbers *between* integers, we often use floating-point numbers,
which can represent small numbers with fine precision, and large numbers with
coarse precision. Floats use 32 bits, and Doubles use 64. Doubles are the
default in Clojure.
```clojure
user=> (type 1.23)
java.lang.Double
user=> (type (float 1.23))
java.lang.Float
```
Floating point math is
[complicated](http://en.wikipedia.org/wiki/Floating_point), and we won’t get
bogged down in the details just yet. The important thing to know is floats and
doubles are *approximations*. There are limits to their correctness:
```clojure
user=> 0.99999999999999999
1.0
```
To represent fractions exactly, we can use the *ratio* type:
```clojure
user=> (type 1/3)
clojure.lang.Ratio
```
### Mathematical operations
The exact behavior of mathematical operations in Clojure depends on their
types. In general, though, Clojure aims to *preserve* information. Adding two
longs returns a long; adding a double and a long returns a double.
```clojure
user=> (+ 1 2)
3
user=> (+ 1 2.0)
3.0
```
`3` and `3.0` are *not* the same number; one is a long, and the other a double. But
for most purposes, they’re equivalent, and Clojure will tell you so:
```clojure
user=> (= 3 3.0)
false
user=> (== 3 3.0)
true
```
`=` asks whether all the things that follow are equal. Since floats are
approximations, `=` considers them different from integers. `==` also compares
things, but a little more loosely: it considers integers equivalent to their
floating-point representations.
We can also subtract with `-`, multiply with `*`, and divide with `/`.
```clojure
user=> (- 3 1)
2
user=> (* 1.5 3)
4.5
user=> (/ 1 2)
1/2
```
Putting the verb first in each list allows us to add or multiply more than one
number in the same step:
```clojure
user=> (+ 1 2 3)
6
user=> (* 2 3 1/5)
6/5
```
Subtraction with more than 2 numbers subtracts all later numbers from the
*first*. Division divides the first number by all the rest.
```clojure
user=> (- 5 1 1 1)
2
user=> (/ 24 2 3)
4
```
By extension, we can define useful interpretations for numeric operations with
just a *single* number:
```clojure
user=> (+ 2)
2
user=> (- 2)
-2
user=> (* 4)
4
user=> (/ 4)
1/4
```
We can also add or multiply a list of no numbers at all, obtaining the additive
and multiplicative identities, respectively. This might seem odd, especially
coming from other languages, but we’ll see later that these generalizations
make it easier to reason about higher-level numeric operations.
```clojure
user=> (+)
0
user=> (*)
1
```
Often, we want to ask which number is bigger, or if one number falls between
two others. `<=` means “less than or equal to”, and asserts that all following
values are in order from smallest to biggest.
```clojure
user=> (<= 1 2 3)
true
user=> (<= 1 3 2)
false
```
`<` means “strictly less than”, and works just like `<=`, except that no two values
may be equal.
```clojure
user=> (<= 1 1 2)
true
user=> (< 1 1 2)
false
```
Their friends `>` and `>=` mean “greater than” and “greater than or equal to”,
respectively, and assert that numbers are in descending order.
```clojure
user=> (> 3 2 1)
true
user=> (> 1 2 3)
false
```
Also commonly used are `inc` and `dec`, which add and subtract one to a number,
respectively:
```clojure
user=> (inc 5)
6
user=> (dec 5)
4
```
One final note: equality tests can take more than 2 numbers as well.
```clojure
user=> (= 2 2 2)
true
user=> (= 2 2 3)
false
```
### Strings
We saw that strings are text, surrounded by double quotes, like `"foo"`. Strings
in Clojure are, like Longs, Doubles, and company, backed by a Java type:
```clojure
user=> (type "cat")
java.lang.String
```
We can make almost *anything* into a string with `str`. Strings, symbols, numbers,
booleans; every value in Clojure has a string representation. Note that `nil`’s
string representation is `""`; an empty string.
```clojure
user=> (str "cat")
"cat"
user=> (str 'cat)
"cat"
user=> (str 1)
"1"
user=> (str true)
"true"
user=> (str '(1 2 3))
"(1 2 3)"
user=> (str nil)
""
```
`str` can also *combine* things together into a single string, which we call
“concatenation”.
```clojure
user=> (str "meow " 3 " times")
"meow 3 times"
```
To look for patterns in text, we can use a [regular
expression](http://www.regular-expressions.info/tutorial.html), which is a tiny
language for describing particular arrangements of text. `re-find` and `re-matches`
look for occurrences of a regular expression in a string. To find a cat:
```clojure
user=> (re-find #"cat" "mystic cat mouse")
"cat"
user=> (re-find #"cat" "only dogs here")
nil
```
That `#"..."` is Clojure’s way of writing a regular expression.
With `re-matches`, you can extract particular parts of a string which match an
expression. Here we find two strings, separated by a `:`. The parentheses mean
that the regular expression should *capture* that part of the match. We get back
a list containing the part of the string that matched the first parentheses,
followed by the part that matched the second parentheses.
```clojure
user=> (rest (re-matches #"(.+):(.+)" "mouse:treat"))
("mouse" "treat")
```
Regular expressions are a powerful tool for searching and matching text,
especially when working with data files. Since regexes work the same in most
languages, you can use any guide online to learn more. It’s not something you
have to master right away; just learn specific tricks as you find you need
them. For a deeper guide, try Fitzgerald’s [Introducing Regular
Expressions](http://shop.oreilly.com/product/0636920012337.do).
### Booleans and logic
Everything in Clojure has a sort of charge, a truth value, sometimes called
“truthiness”. `true` is positive and `false` is negative. `nil` is negative, too.
```clojure
user=> (boolean true)
true
user=> (boolean false)
false
user=> (boolean nil)
false
```
Every other value in Clojure is positive.
```clojure
user=> (boolean 0)
true
user=> (boolean 1)
true
user=> (boolean "hi there")
true
user=> (boolean str)
true
```
If you’re coming from a C-inspired language, where 0 is considered false, this
might be a bit surprising. Likewise, in much of POSIX, 0 is considered success
and nonzero values are failures. Lisp allows no such confusion: the only
negative values are `false` and `nil`.
We can reason about truth values using `and`, `or`, and `not`. and returns the first
negative value, or the last value if all are truthy.
```clojure
user=> (and true false true)
false
user=> (and true true true)
true
user=> (and 1 2 3)
3
```
Similarly, `or` returns the first positive value.
```clojure
user=> (or false 2 3)
2
user=> (or false nil)
nil
```
And `not` inverts the logical sense of a value:
```clojure
user=> (not 2)
false
user=> (not nil)
true
```
We’ll learn more about Boolean logic when we start talking about *control flow*;
the way we alter evaluation of a program and express ideas like “if I’m a cat,
then meow incessantly”.
### Symbols
We saw symbols in the previous chapter; they’re bare strings of characters,
like `foo` or `+.`
```clojure
user=> (class 'str)
clojure.lang.Symbol
```
Symbols can have either short or full names. The short name is used to refer to
things locally. The *fully qualified* name is used to refer unambiguously to a
symbol from anywhere. If I were a symbol, my name would be “Kyle”, and my full
name “Kyle Kingsbury.”
Symbol names are separated with a `/`. For instance, the symbol `str` is also
present in a family called `clojure.core`; the corresponding full name is
`clojure.core/str`.
```clojure
user=> (= str clojure.core/str)
true
user=> (name 'clojure.core/str)
"str"
```
When we talked about the maximum size of an integer, that was a fully-qualified
symbol, too.
```clojure
(type 'Integer/MAX_VALUE)
clojure.lang.Symbol
```
The job of symbols is to *refer* to things, to *point* to other values. When
evaluating a program, symbols are looked up and replaced by their corresponding
values. That’s not the only use of symbols, but it’s the most common.
### Keywords
Closely related to symbols and strings are *keywords*, which begin with a `:`.
Keywords are like strings in that they’re made up of text, but are specifically
intended for use as *labels* or *identifiers*. These aren’t labels in the sense of
symbols: keywords aren’t replaced by any other value. They’re just names, by
themselves.
```clojure
user=> (type :cat)
clojure.lang.Keyword
user=> (str :cat)
":cat"
user=> (name :cat)
"cat"
```
As labels, keywords are most useful when paired with other values in a
collection, like a *map*. Keywords can also be used as verbs to *look up specific
values* in other data types. We’ll learn more about keywords shortly.
### Lists
A collection is a group of values. It’s a *container* which provides some
structure, some framework, for the things that it holds. We say that a
collection contains *elements*, or *members*. We saw one kind of collection–a
list–in the previous chapter.
```clojure
user=> '(1 2 3)
(1 2 3)
user=> (type '(1 2 3))
clojure.lang.PersistentList
```
Remember, we *quote* lists with a `'` to prevent them from being evaluated. You can
also construct a list using `list`:
```clojure
user=> (list 1 2 3)
(1 2 3)
```
Lists are comparable just like every other value:
```clojure
user=> (= (list 1 2) (list 1 2))
true
```
You can modify a list by `conj`oining an element onto it:
```clojure
user=> (conj '(1 2 3) 4)
(4 1 2 3)
```
We added 4 to the list–but it appeared at the *front*. Why? Internally, lists are
stored as a *chain* of values: each link in the chain is a tiny box which holds
the value and a connection to the next link. This data structure, called a
linked list, offers immediate access to the first element.
```clojure
user=> (first (list 1 2 3))
1
```
But getting to the second element requires an extra hop down the chain
```clojure
user=> (second (list 1 2 3))
2
```
and the third element a hop after that, and so on.
```clojure
user=> (nth (list 1 2 3) 2)
3
```
`nth` gets the element of an ordered collection at a particular *index*. The first
element is index 0, the second is index 1, and so on.
This means that lists are well-suited for small collections, or collections
which are read in linear order, but are slow when you want to get arbitrary
elements from later in the list. For fast access to every element, we use a
*vector*.
### Vectors
Vectors are surrounded by square brackets, just like lists are surrounded by
parentheses. Because vectors *aren’t* evaluated like lists are, there’s no need
to quote them:
```clojure
user=> [1 2 3]
[1 2 3]
user=> (type [1 2 3])
clojure.lang.PersistentVector
```
You can also create vectors with `vector`, or change other structures into
vectors with `vec`:
```clojure
user=> (vector 1 2 3)
[1 2 3]
user=> (vec (list 1 2 3))
[1 2 3]
```
`conj` on a vector adds to the *end*, not the *start*:
```clojure
user=> (conj [1 2 3] 4)
[1 2 3 4]
```
Our friends `first`, `second`, and `nth` work here too; but unlike lists, nth is *fast*
on vectors. That’s because internally, vectors are represented as a very broad
tree of elements, where each part of the tree branches into 32 smaller trees.
Even very large vectors are only a few layers deep, which means getting to
elements only takes a few hops.
In addition to `first`, you’ll often want to get the *remaining* elements in a
collection. There are two ways to do this:
```clojure
user=> (rest [1 2 3])
(2 3)
user=> (next [1 2 3])
(2 3)
```
`rest` and `next` both return “everything but the first element”. They differ only
by what happens when there are no remaining elements:
```clojure
user=> (rest [1])
()
user=> (next [1])
nil
```
rest returns logical true, next returns logical false. Each has their uses, but
in almost every case they’re equivalent–I interchange them freely.
We can get the final element of any collection with `last`:
```clojure
user=> (last [1 2 3])
3
```
And figure out how big the vector is with `count`:
```clojure
user=> (count [1 2 3])
3
```
Because vectors are intended for looking up elements by index, we can also use
them directly as *verbs*:
```
user=> ([:a :b :c] 1)
:b
```
So we took the vector containing three keywords, and asked “What’s the element
at index 1?” Lisp, like most (but not all!) modern languages, counts up from
*zero*, not one. Index 0 is the first element, index 1 is the second element, and
so on. In this vector, finding the element at index 1 evaluates to `:b`.
Finally, note that vectors and lists containing the same elements are
considered equal in Clojure:
```clojure
user=> (= '(1 2 3) [1 2 3])
true
```
In almost all contexts, you can consider vectors, lists, and other sequences as
interchangeable. They only differ in their performance characteristics, and in
a few data-structure-specific operations.
### Sets
Sometimes you want an unordered collection of values; especially when you plan
to ask questions like “does the collection have the number 3 in it?” Clojure,
like most languages, calls these collections sets.
```clojure
user=> #{:a :b :c}
#{:a :c :b}
```
Sets are surrounded by `#{...}`. Notice that though we gave the elements `:a`, `:b`,
and `:c`, they came out in a different order. In general, the order of sets can
shift at any time. If you want a particular order, you can ask for it as a list
or vector:
```clojure
user=> (vec #{:a :b :c})
[:a :c :b]
```
Or ask for the elements in sorted order:
```clojure
(sort #{:a :b :c})
(:a :b :c)
```
`conj` on a set adds an element:
```clojure
user=> (conj #{:a :b :c} :d)
#{:a :c :b :d}
user=> (conj #{:a :b :c} :a)
#{:a :c :b}
```
Sets never contain an element more than once, so `conj`ing an element which is
already present does nothing. Conversely, one removes elements with `disj`:
```clojure
user=> (disj #{"hornet" "hummingbird"} "hummingbird")
#{"hornet"}
````
The most common operation with a set is to check whether something is inside
it. For this we use `contains`?.
```clojure
user=> (contains? #{1 2 3} 3)
true
user=> (contains? #{1 2 3} 5)
false
```
Like vectors, you can use the set *itself* as a verb. Unlike `contains?`, this
expression returns the element itself (if it was present), or `nil`.
```clojure
user=> (#{1 2 3} 3)
3
user=> (#{1 2 3} 4)
nil
```
You can make a set out of any other collection with `set`.
```clojure
user=> (set [:a :b :c])
#{:a :c :b}
```
### Maps
The last collection on our tour is the *map*: a data structure which associates
*keys* with *values*. In a dictionary, the keys are words and the definitions are
the values. In a library, keys are call signs, and the books are values. Maps
are indexes for looking things up, and for representing different pieces of
named information together. Here’s a cat:
```clojure
user=> {:name "mittens" :weight 9 :color "black"}
{:weight 9, :name "mittens", :color "black"}
```
Maps are surrounded by braces `{...}`, filled by alternating keys and values. In
this map, the three keys are `:name`, `:color`, and `:weight`, and their values are
`"mittens"`, `"black"`, and 9, respectively. We can look up the corresponding value
for a key with `get`:
```clojure
user=> (get {"cat" "meow" "dog" "woof"} "cat")
"meow"
user=> (get {:a 1 :b 2} :c)
nil
```
`get` can also take a *default* value to return instead of nil, if the key doesn’t
exist in that map.
```clojure
user=> (get {:glinda :good} :wicked :not-here)
:not-here
```
Since lookups are so important for maps, we can use a map as a verb directly:
```clojure
user=> ({"amlodipine" 12 "ibuprofen" 50} "ibuprofen")
50
```
And conversely, keywords can also be used as verbs, which look themselves up in
maps:
```clojure
user=> (:raccoon {:weasel "queen" :raccoon "king"})
"king"
```
You can add a value for a given key to a map with `assoc`.
```clojure
user=> (assoc {:bolts 1088} :camshafts 3)
{:camshafts 3 :bolts 1088}
user=> (assoc {:camshafts 3} :camshafts 2)
{:camshafts 2}
```
Assoc adds keys if they aren’t present, and *replaces* values if they’re already
there. If you associate a value onto `nil`, it creates a new map.
```clojure
user=> (assoc nil 5 2)
{5 2}
```
You can combine maps together using `merge`, which yields a map containing all
the elements of all given maps, preferring the values from later ones.
```clojure
user=> (merge {:a 1 :b 2} {:b 3 :c 4})
{:c 4, :a 1, :b 3}
```
Finally, to remove a value, use `dissoc`.
```clojure
user=> (dissoc {:potatoes 5 :mushrooms 2} :mushrooms)
{:potatoes 5}
```
### Putting it all together
All these collections and types can be combined freely. As software engineers,
we model the world by creating a particular *representation* of the problem in
the program. Having a rich set of values at our disposal allows us to talk
about complex problems. We might describe a person:
```clojure
{:name "Amelia Earhart"
:birth 1897
:death 1939
:awards {"US" #{"Distinguished Flying Cross" "National Women's Hall of Fame"}
"World" #{"Altitude record for Autogyro" "First to cross Atlantic twice"}}}
```
Or a recipe:
```clojure
{:title "Chocolate chip cookies"
:ingredients {"flour" [(+ 2 1/4) :cup]
"baking soda" [1 :teaspoon]
"salt" [1 :teaspoon]
"butter" [1 :cup]
"sugar" [3/4 :cup]
"brown sugar" [3/4 :cup]
"vanilla" [1 :teaspoon]
"eggs" 2
"chocolate chips" [12 :ounce]}}
```
Or the Gini coefficients of nations, as measured over time:
```
{"Afghanistan" {2008 27.8}
"Indonesia" {2008 34.1 2010 35.6 2011 38.1}
"Uruguay" {2008 46.3 2009 46.3 2010 45.3}}
```
In Clojure, we *compose* data structures to form more complex values; to talk
about bigger ideas. We use operations like `first`, `nth`, `get`, and `contains?` to
extract specific information from these structures, and modify them using `conj`,
`disj`, `assoc`, `dissoc`, and so on.
We started this chapter with a discussion of *types*: groups of similar objects
which obey the same rules. We learned that bigints, longs, ints, shorts, and
bytes are all integers, that doubles and floats are approximations to decimal
numbers, and that ratios represent fractions exactly. We learned the
differences between strings for text, symbols as references, and keywords as
short labels. Finally, we learned how to compose, alter, and inspect
collections of elements. Armed with the basic nouns of Clojure, we’re ready to
write a broad array of programs.
I’d like to conclude this tour with one last type of value. We’ve inspected
dozens of types so far–but what what happens when you turn the camera on
itself?
```clojure
user=> (type type)
clojure.core$type
```
What *is* this `type` thing, exactly? What *are* these verbs we’ve been learning, and
where do they come from? This is the central question of chapter three:
functions.
## Functions
We left off last chapter with a question: what *are* verbs, anyway? When you
evaluate `(type :mary-poppins)`, what really happens?
```clojure
user=> (type :mary-poppins)
clojure.lang.Keyword
```
To understand how `type` works, we’ll need several new ideas. First, we’ll expand
on the notion of symbols as references to other values. Then we’ll learn about
functions: Clojure’s verbs. Finally, we’ll use the Var system to explore and
change the definitions of those functions.
### Let bindings
We know that symbols are names for things, and that when evaluated, Clojure
replaces those symbols with their corresponding values. `+`, for instance, is a
symbol which points to the verb `#`.
```clojure
user=> +
#
```
When you try to use a symbol which has no defined meaning, Clojure refuses:
```clojure
user=> cats
CompilerException java.lang.RuntimeException: Unable to resolve symbol: cats in this context, compiling:(NO_SOURCE_PATH:0:0)
```
But we can define a meaning for a symbol within a specific expression, using `let`.
```clojure
user=> (let [cats 5] (str "I have " cats " cats."))
"I have 5 cats."
```
The `let` expression first takes a vector of *bindings*: alternating symbols and
values that those symbols are *bound* to, within the remainder of the expression.
“Let the symbol `cats` be 5, and construct a string composed of `"I have "`, `cats`,
and `" cats"`.
Let bindings apply only within the let expression itself. They also override
any existing definitions for symbols at that point in the program. For
instance, we can redefine addition to mean subtraction, for the duration of a
`let`:
```clojure
user=> (let [+ -] (+ 2 3))
-1
```
But that definition doesn’t apply outside the let:
```clojure
user=> (+ 2 3)
5
```
We can also provide *multiple* bindings. Since Clojure doesn’t care about
spacing, alignment, or newlines, I’ll write this on multiple lines for clarity.
```clojure
user=> (let [person "joseph"
num-cats 186]
(str person " has " num-cats " cats!"))
"joseph has 186 cats!"
```
When multiple bindings are given, they are evaluated in order. Later bindings
can use previous bindings.
```clojure
user=> (let [cats 3
legs (* 4 cats)]
(str legs " legs all together"))
"12 legs all together"
```
So fundamentally, `let` defines the meaning of symbols within an expression. When
Clojure evaluates a `let`, it replaces all occurrences of those symbols in the
rest of the `let` expression with their corresponding values, then evaluates the
rest of the expression.
### Functions
We saw in chapter one that Clojure evaluates lists by *substituting* some other
value in their place:
```clojure
user=> (inc 1)
2
```
`inc` takes any number, and is replaced by that number plus one. That sounds an
awful lot like a let:
```clojure
user=> (let [x 1] (+ x 1))
2
```
If we bound `x` to `5` instead of `1`, this expression would evaluate to `6`. We can
think about `inc` like a let expression, but without particular values provided
for the symbols.
```clojure
(let [x] (+ x 1))
```
We can’t actually evaluate this program, because there’s no value for `x` yet. It
could be 1, or 4, or 1453. We say that `x` is *unbound*, because it has no binding
to a particular value. This is the nature of the *function*: an expression with
unbound symbols.
```clojure
user=> (fn [x] (+ x 1))
#
```
Does the name of that function remind you of anything?
```clojure
user=> inc
#
```
Almost all verbs in Clojure are functions. Functions represent unrealized
computation: expressions which are not yet evaluated, or incomplete. This
particular function works just like `inc`: it’s an expression which has a single
unbound symbol, `x`. When we *invoke* the function with a particular value, the
expressions in the function are evaluated with `x` bound to that value.
```clojure
user=> (inc 2)
3
user=> ((fn [x] (+ x 1)) 2)
3
```
We say that `x` is this function’s *argument*, or *parameter*. When Clojure evaluates
`(inc 2)`, we say that `inc` is *called* with `2`, or that `2` is passed to `inc`. The
result of that *function invocation* is the function’s *return value*. We say that
`(inc 2)` *returns* `3`.
Fundamentally, functions describe the relationship between arguments and return
values: given `1`, return `2`. Given `2`, return `3`, and so on. Let bindings describe
a similar relationship, but with a specific set of values for those arguments.
`let` is evaluated immediately, whereas `fn` is evaluated *later*, when bindings are
provided.
There’s a shorthand for writing functions, too: `#(+ % 1)` is equivalent to `(fn
[x] (+ x 1))`. `%` takes the place of the first argument to the function. You’ll
sometime see `%1`, `%2`, etc. used for the first argument, second argument, and so
on.
```clojure
user=> (let [burrito #(list "beans" % "cheese")]
(burrito "carnitas"))
("beans" "carnitas" "cheese")
```
Since functions exist to *defer* evaluation, there’s no sense in creating and
invoking them in the same expression as we’ve done here. What we want is to
give *names* to our functions, so they can be recombined in different ways.
```clojure
user=> (let [twice (fn [x] (* 2 x))]
(+ (twice 1)
(twice 3)))
8
```
Compare that expression to an equivalent, expanded form:
```clojure
user=> (+ (* 2 1)
(* 2 3))
```
The name `twice` is gone, and in its place is the same sort of computation – `(* 2
something)` – written twice. While we *could* represent our programs as a single
massive expression, it’d be impossible to reason about. Instead, we use
functions to compact redundant expressions, by isolating common patterns of
computation. Symbols help us re-use those functions (and other values) in more
than one place. By giving the symbols meaningful names, we make it easier to
reason about the structure of the program as a whole; breaking it up into
smaller, understandable parts.
This is core pursuit of software engineering: organizing expressions. Almost
every programming language is in search of the right tools to break apart,
name, and recombine expressions to solve large problems. In Clojure we’ll see
one particular set of tools for composing programs, but the underlying ideas
will transfer to many other languages.
### Vars
We’ve used `let` to define a symbol within an expression, but what about the
default meanings of `+`, `conj`, and `type`? Are they also `let` bindings? Is the whole
universe one giant `let`?
Well, not exactly. That’s one way to think about default bindings, but it’s
brittle. We’d need to wrap our whole program in a new `let` expression every time
we wanted to change the meaning of a symbol. And moreover, once a `let` is
defined, there’s no way to change it. If we want to redefine symbols for
everyone–even code that we didn’t write–we need a new construct: a *mutable*
variable.
```clojure
user=> (def cats 5)
#'user/cats
user=> (type #'user/cats)
clojure.lang.Var
````
`def` *defines* a type of value we haven’t seen before: a var. Vars, like symbols,
are references to other values. When evaluated, a symbol pointing to a var is
replaced by the var’s corresponding value:
```clojure
user=> user/cats
5
```
`def` also *binds* the symbol `cats` (and its globally qualified equivalent
`user/cats`) to that var.
```clojure
user=> user/cats
5
user=> cats
5
```
When we said in chapter one that `inc`, `list`, and friends were symbols that
pointed to functions, that wasn’t the whole story. The symbol `inc` points to the
var `#'inc`, which in turn points to the function `#`. We can see the intermediate var with `resolve`:
```clojure
user=> 'inc
inc ; the symbol
user=> (resolve 'inc)
#'clojure.core/inc ; the var
user=> (eval 'inc)
# ; the value
```
Why two layers of indirection? Because unlike the symbol, we can *change* the
meaning of a Var for everyone, globally, at any time.
```clojure
user=> (def astronauts [])
#'user/astronauts
user=> (count astronauts)
0
user=> (def astronauts ["Sally Ride" "Guy Bluford"])
#'user/astronauts
user=> (count astronauts)
2
```
Notice that `astronauts` had *two* distinct meanings, depending on when we
evaluated it. After the first `def`, astronauts was an empty vector. After the
second `def`, it had one entry.
If this seems dangerous, you’re a smart cookie. Redefining names in this way
changes the meaning of expressions *everywhere* in a program, without warning.
Expressions which relied on the value of a Var could suddenly take on new,
possibly incorrect, meanings. It’s a powerful tool for experimenting at the
REPL, and for updating a running program, but it can have unexpected
consequences. Good Clojurists use `def` to set up a program initially, and only
change those definitions with careful thought.
Totally redefining a Var isn’t the only option. There are safer, controlled
ways to change the meaning of a Var within a particular part of a program,
which we’ll explore later.
### Defining functions
Armed with *def*, we’re ready to create our own named functions in Clojure.
```clojure
user=> (def half (fn [number] (/ number 2)))
#'user/half
user=> (half 6)
3
```
Creating a function and binding it to a var is so common that it has its own
form: `defn`, short for `def` `fn`.
```clojure
user=> (defn half [number] (/ number 2))
#'user/half
```
Functions don’t have to take an argument. We’ve seen functions which take zero
arguments, like `(+)`.
```clojure
user=> (defn half [] 1/2)
#'user/half
user=> (half)
1/2
```
But if we try to use our earlier form with one argument, Clojure complains that
the *arity* – the number of arguments to the function–is incorrect.
```clojure
user=> (half 10)
ArityException Wrong number of args (1) passed to: user$half clojure.lang.AFn.throwArity (AFn.java:437)
```
To handle *multiple* arities, functions have an alternate form. Instead of an
argument vector and a body, one provides a series of lists, each of which
starts with an argument vector, followed by the body.
```clojure
user=> (defn half
([] 1/2)
([x] (/ x 2)))
user=> (half)
1/2
user=> (half 10)
5
```
Multiple arguments work just like you expect. Just specify an argument vector
of two, or three, or however many arguments the function takes.
```clojure
user=> (defn add
[x y]
(+ x y))
#'user/add
user=> (add 1 2)
3
```
Some functions can take *any* number of arguments. For that, Clojure provides `&`,
which slurps up all remaining arguments as a list:
```clojure
user=> (defn vargs
[x y & more-args]
{:x x
:y y
:more more-args})
#'user/vargs
user=> (vargs 1)
ArityException Wrong number of args (1) passed to: user$vargs clojure.lang.AFn.throwArity (AFn.java:437)
user=> (vargs 1 2)
{:x 1, :y 2, :more nil}
user=> (vargs 1 2 3 4 5)
{:x 1, :y 2, :more (3 4 5)}
```
Note that `x` and `y` are mandatory, though there don’t have to be any remaining
arguments.
To keep track of what arguments a function takes, why the function exists, and
what it does, we usually include a *docstring*. Docstrings help fill in the
missing context around functions, to explain their assumptions, context, and
purpose to the world.
```clojure
(defn launch
"Launches a spacecraft into the given orbit by initiating a
controlled on-axis burn. Does not automatically stage, but
does vector thrust, if the craft supports it."
[craft target-orbit]
"OK, we don't know how to control spacecraft yet.")
```
Docstrings are used to automatically generate documentation for Clojure
programs, but you can also access them from the REPL.
```clojure
user=> (doc launch)
-------------------------
user/launch
([craft target-orbit])
Launches a spacecraft into the given orbit by initiating a
controlled on-axis burn. Does not automatically stage, but
does vector thrust, if the craft supports it.
nil
```
`doc` tells us the full name of the function, the arguments it accepts, and its
docstring. This information comes from the `#'launch` var’s *metadata*, and is
saved there by `defn`. We can inspect metadata directly with the `meta` function:
```clojure
(meta #'launch)
{:arglists ([craft target-orbit]), :ns #, :name launch, :column 1, :doc "Launches a spacecraft into the given orbit.", :line 1, :file "NO_SOURCE_PATH"}
There’s some other juicy information in there, like the file the function was
defined in and which line and column it started at, but that’s not particularly
useful since we’re in the REPL, not a file. However, this *does* hint at a way to
answer our motivating question: how does the `type` function work?
```
### How does type work?
We know that `type` returns the type of an object:
```clojure
user=> (type 2)
java.lang.long
```
And that `type`, like all functions, is a kind of object with its own unique type:
````clojure
user=> type
#
user=> (type type)
clojure.core$type
```
This tells us that `type` is a particular *instance*, at memory address `39bda9b9`,
of the type `clojure.core$type`. `clojure.core` is a namespace which defines the
fundamentals of the Clojure language, and `$type` tells us that it’s named `type`
in that namespace. None of this is particularly helpful, though. Maybe we can
find out more about the `clojure.core$type` by asking what its *supertypes* are:
```clojure
user=> (supers (type type))
#{clojure.lang.AFunction clojure.lang.IMeta java.util.concurrent.Callable clojure.lang.Fn clojure.lang.AFn java.util.Comparator java.lang.Object clojure.lang.RestFn clojure.lang.IObj java.lang.Runnable java.io.Serializable clojure.lang.IFn}
```
This is a set of all the types that include `type`. We say that `type` is an
*instance* of `clojure.lang.AFunction`, or that it *implements* or *extends*
`java.util.concurrent.Callable`, and so on. Since it’s a member of
`clojure.lang.IMeta` it has metadata, and since it’s a member of
`clojure.lang.AFn`, it’s a function. Just to double check, let’s confirm that
`type` is indeed a function:
```clojure
user=> (fn? type)
true
```
What about its documentation?
```clojure
user=> (doc type)
-------------------------
clojure.core/type
([x])
Returns the :type metadata of x, or its Class if none
nil
```
Ah, that’s helpful. `type` can take a single argument, which it calls `x`. If it
has `:type` metadata, that’s what it returns. Otherwise, it returns the class of
x. Let’s take a deeper look at `type`‘s metadata for more clues.
```clojure
user=> (meta #'type)
{:ns #, :name type, :arglists ([x]), :column 1, :added "1.0", :static true, :doc "Returns the :type metadata of x, or its Class if none", :line 3109, :file "clojure/core.clj"}
````
Look at that! This function was first added to Clojure in version 1.0, and is
defined in the file `clojure/core.clj`, on line 3109. We could go dig up the
Clojure source code and read its definition there–or we could ask Clojure to do
it for us:
```clojure
user=> (source type)
(defn type
"Returns the :type metadata of x, or its Class if none"
{:added "1.0"
:static true}
[x]
(or (get (meta x) :type) (class x)))
nil
```
Aha! Here, at last, is how `type` works. It’s a function which takes a single
argument `x`, and returns either `:type` from its metadata, or `(class x)`.
We can delve into any function in Clojure using these tools:
```clojure
user=> (source +)
(defn +
"Returns the sum of nums. (+) returns 0. Does not auto-promote
longs, will throw on overflow. See also: +'"
{:inline (nary-inline 'add 'unchecked_add)
:inline-arities >1?
:added "1.2"}
([] 0)
([x] (cast Number x))
([x y] (. clojure.lang.Numbers (add x y)))
([x y & more]
(reduce1 + (+ x y) more)))
nil
```
Almost every function in a programming language is made up of other, simpler
functions. `+`, for instance, is defined in terms of `cast`, `add`, and `reduce1`.
Sometimes functions are defined in terms of themselves. `+` uses itself twice in
this definition; a technique called *recursion*.
At the bottom, though, are certain fundamental constructs below which you can
go no further. Core axioms of the language. Lisp calls these "special forms”.
`def` and `let` are special forms (well–almost: `let` is a thin wrapper around `let*`,
which is a special form) in Clojure. These forms are defined by the core
implementation of the language, and are not reducible to other Clojure
expressions.
```clojure
user=> (source def)
Source not found
```
Some Lisps are written *entirely* in terms of a few special forms, but Clojure is
much less pure. Many functions bottom out in Java functions and types, or, for
CLJS, in terms of Javascript. Any time you see an expression like `(.
clojure.lang.Numbers (add x y))`, there’s Java code underneath. Below Java lies
the JVM, which might be written in C or C++, depending on which one you use.
And underneath C and C++ lie more libraries, the operating system, assembler,
microcode, registers, and ultimately, electrons flowing through silicon.
A well-designed language *isolates* you from details you don’t need to worry
about, like which logic gates or registers to use, and lets you focus on the
task at hand. Good languages also need to allow escape hatches for performance
or access to dangerous functionality, as we saw with Vars. You can write entire
programs entirely in terms of Clojure, but sometimes, for performance or to use
tools from other languages, you’ll rely on Java. The Clojure code is easy to
explore with `doc` and `source`, but Java can be more opaque–I usually rely on the
java source files and online documentation.
### Review
We’ve seen how `let` associates names with values in a particular expression, and
how Vars allow for *mutable* bindings which apply universally. and whose
definitions can change over time. We learned that Clojure verbs are functions,
which express the general shape of an expression but with certain values
*unbound*. Invoking a function *binds* those variables to specific values, allowing
evaluation of the function to proceed.
Functions *decompose* programs into simpler pieces, expressed in terms of one
another. Short, meaningful names help us understand what those functions (and
other values) mean.
Finally, we learned how to introspect Clojure functions with `doc` and
`source`, and saw the definition of some basic Clojure functions. The [Clojure
cheatsheet](http://clojure.org/cheatsheet) gives a comprehensive list of the
core functions in the language, and is a great starting point when you have to
solve a problem but don’t know what functions to use.
We’ll see a broad swath of those functions in Chapter 4: Sequences.
*My thanks to Zach Tellman, Kelly Sommers, and Michael R Bernstein for reviewing
drafts of this chapter.*
## Sequences
In Chapter 3, we discovered functions as a way to abstract expressions; to
rephrase a particular computation with some parts missing. We used functions to
transform a single value. But what if we want to apply a function to more than
one value at once?
### What about sequences?
For example, we know that (inc 2) increments the number 2. What if we wanted to
increment every number in the vector [1 2 3], producing [2 3 4]?
```clojure
user=> (inc [1 2 3])
ClassCastException clojure.lang.PersistentVector cannot be cast to java.lang.Number clojure.lang.Numbers.inc (Numbers.java:110)
```
Clearly inc can only work on numbers, not on vectors. We need a different kind
of tool.
### A direct approach
Let’s think about the problem in concrete terms. We want to increment each of
three elements: the first, second, and third. We know how to get an element
from a sequence by using nth, so let’s start with the first number, at index 0:
```clojure
user=> (def numbers [1 2 3])
#'user/numbers
user=> (nth numbers 0)
1
user=> (inc (nth numbers 0))
2
```
So there’s the first element incremented. Now we can do the second:
```clojure
user=> (inc (nth numbers 1))
3
user=> (inc (nth numbers 2))
4
```
And it should be straightforward to combine these into a vector…
```clojure
user=> [(inc (nth numbers 0)) (inc (nth numbers 1)) (inc (nth numbers 2))]
[2 3 4]
```
Success! We’ve incremented each of the numbers in the list! How about a list
with only two elements?
```clojure
user=> (def numbers [1 2])
#'user/numbers
user=> [(inc (nth numbers 0)) (inc (nth numbers 1)) (inc (nth numbers 2))]
IndexOutOfBoundsException clojure.lang.PersistentVector.arrayFor (PersistentVector.java:107)
```
Shoot. We tried to get the element at index 2, but couldn’t, because numbers
only has indices 0 and 1. Clojure calls that “index out of bounds”.
We could just leave off the third expression in the vector; taking only
elements 0 and 1. But the problem actually gets much worse, because we’d need
to make this change every time we wanted to use a different sized vector. And
what of a vector with 1000 elements? We’d need 1000 (inc (nth numbers ...))
expressions! Down this path lies madness.
Let’s back up a bit, and try a slightly smaller problem.
### Recursion
What if we just incremented the first number in the vector? How would that
work? We know that first finds the first element in a sequence, and rest finds
all the remaining ones.
```clojure
user=> (first [1 2 3])
1
user=> (rest [1 2 3])
(2 3)
```
So there’s the pieces we’d need. To glue them back together, we can use a
function called cons, which says “make a list beginning with the first
argument, followed by all the elements in the second argument”.
```clojure
user=> (cons 1 [2])
(1 2)
user=> (cons 1 [2 3])
(1 2 3)
user=> (cons 1 [2 3 4])
(1 2 3 4)
```
OK so we can split up a sequence, increment the first part, and join them back
together. Not so hard, right?
```clojure
(defn inc-first [nums]
(cons (inc (first nums))
(rest nums)))
user=> (inc-first [1 2 3 4])
(2 2 3 4)
```
Hey, there we go! First element changed. Will it work with any length list?
```clojure
user=> (inc-first [5])
(6)
user=> (inc-first [])
NullPointerException clojure.lang.Numbers.ops (Numbers.java:942)
```
Shoot. We can’t increment the first element of this empty vector, because it
doesn’t have a first element.
```clojure
user=> (first [])
nil
user=> (inc nil)
NullPointerException clojure.lang.Numbers.ops (Numbers.java:942)
```
So there are really two cases for this function. If there is a first element in
nums, we’ll increment it as normal. If there’s no such element, we’ll return an
empty list. To express this kind of conditional behavior, we’ll use a Clojure
special form called if:
```clojure
user=> (doc if)
-------------------------
if
(if test then else?)
Special Form
Evaluates test. If not the singular values nil or false,
evaluates and yields then, otherwise, evaluates and yields else. If
else is not supplied it defaults to nil.
Please see http://clojure.org/special_forms#if
```
To confirm our intuition:
```clojure
user=> (if true :a :b)
:a
user=> (if false :a :b)
:b
```
Seems straightforward enough.
```clojure
(defn inc-first [nums]
(if (first nums)
; If there's a first number, build a new list with cons
(cons (inc (first nums))
(rest nums))
; If there's no first number, just return an empty list
(list)))
user=> (inc-first [])
()
user=> (inc-first [1 2 3])
(2 2 3)
```
Success! Now we can handle both cases: empty sequences, and sequences with
things in them. Now how about incrementing that second number? Let’s stare at
that code for a bit.
```clojure
(rest nums)
```
Hang on. That list–(rest nums)–that’s a list of numbers too. What if we… used
our inc-first function on that list, to increment its first number? Then we’d
have incremented both the first and the second element.
```clojure
(defn inc-more [nums]
(if (first nums)
(cons (inc (first nums))
(inc-more (rest nums)))
(list)))
user=> (inc-more [1 2 3 4])
(2 3 4 5)
```
Odd. That didn’t just increment the first two numbers. It incremented all the
numbers. We fell into the complete solution entirely by accident. What happened
here?
Well first we… yes, we got the number one, and incremented it. Then we stuck
that onto (inc-first [2 3 4]), which got two, and incremented it. Then we stuck
that two onto (inc-first [3 4]), which got three, and then we did the same for
four. Only that time around, at the very end of the list, (rest [4]) would have
been empty. So when we went to get the first number of the empty list, we took
the second branch of the if, and returned the empty list.
Having reached the bottom of the function calls, so to speak, we zip back up
the chain. We can imagine this function turning into a long string of cons
calls, like so:
```clojure
(cons 2 (cons 3 (cons 4 (cons 5 '()))))
(cons 2 (cons 3 (cons 4 '(5))))
(cons 2 (cons 3 '(4 5)))
(cons 2 '(3 4 5))
'(2 3 4 5)
```
This technique is called recursion, and it is a fundamental principle in
working with collections, sequences, trees, or graphs… any problem which has
small parts linked together. There are two key elements in a recursive program:
1. Some part of the problem which has a known solution
2. A relationship which connects one part of the problem to the next
Incrementing the elements of an empty list returns the empty list. This is our
base case: the ground to build on. Our inductive case, also called the
recurrence relation, is how we broke the problem up into incrementing the first
number in the sequence, and incrementing all the numbers in the rest of the
sequence. The if expression bound these two cases together into a single
function; a function defined in terms of itself.
Once the initial step has been taken, every step can be taken.
```clojure
user=> (inc-more [1 2 3 4 5 6 7 8 9 10 11 12])
(2 3 4 5 6 7 8 9 10 11 12 13)
```
This is the beauty of a recursive function; folding an unbounded stream of
computation over and over, onto itself, until only a single step remains.
### Generalizing from inc
We set out to increment every number in a vector, but nothing in our solution
actually depended on inc. It just as well could have been dec, or str, or
keyword. Let’s parameterize our inc-more function to use any transformation of
its elements:
```clojure
(defn transform-all [f xs]
(if (first xs)
(cons (f (first xs))
(transform-all f (rest xs)))
(list)))
```
Because we could be talking about any kind of sequence, not just numbers, we’ve
named the sequence xs, and its first element x. We also take a function f as an
argument, and that function will be applied to each x in turn. So not only can
we increment numbers…
```clojure
user=> (transform-all inc [1 2 3 4])
(2 3 4 5)
```
…but we can turn strings to keywords…
```clojure
user=> (transform-all keyword ["bell" "hooks"])
(:bell :hooks)
…or wrap every element in a list:
user=> (transform-all list [:codex :book :manuscript])
((:codex) (:book) (:manuscript))
```
In short, this function expresses a sequence in which each element is some
function applied to the corresponding element in the underlying sequence. This
idea is so important that it has its own name, in mathematics, Clojure, and
other languages. We call it map.
```clojure
user=> (map inc [1 2 3 4])
(2 3 4 5)
```
You might remember maps as a datatype in Clojure, too–they’re dictionaries that
relate keys to values.
```clojure
{:year 1969
:event "moon landing"}
```
The function map relates one sequence to another. The type map relates keys to
values. There is a deep symmetry between the two: maps are usually sparse, and
the relationships between keys and values may be arbitrarily complex. The map
function, on the other hand, usually expresses the same type of relationship,
applied to a series of elements in fixed order.
### Building sequences
Recursion can do more than just map. We can use it to expand a single value
into a sequence of values, each related by some function. For instance:
```clojure
(defn expand [f x count]
(if (pos? count)
(cons x (expand f (f x) (dec count)))))
```
Our base case is x itself, followed by the sequence beginning with (f x). That
sequence in turn expands to (f (f x)), and then (f (f (f x))), and so on. Each
time we call expand, we count down by one using dec. Once the count is zero,
the if returns nil, and evaluation stops. If we start with the number 0 and use
inc as our function:
```clojure
user=> user=> (expand inc 0 10)
(0 1 2 3 4 5 6 7 8 9)
```
Clojure has a more general form of this function, called iterate.
```clojure
user=> (take 10 (iterate inc 0))
(0 1 2 3 4 5 6 7 8 9)
```
Since this sequence is infinitely long, we’re using take to select only the
first 10 elements. We can construct more complex sequences by using more
complex functions:
```clojure
user=> (take 10 (iterate (fn [x] (if (odd? x) (+ 1 x) (/ x 2))) 10))
(10 5 6 3 4 2 1 2 1 2)
```
Or build up strings:
```clojure
user=> (take 5 (iterate (fn [x] (str x "o")) "y"))
("y" "yo" "yoo" "yooo" "yoooo")
```
iterate is extremely handy for working with infinite sequences, and has some
partners in crime. repeat, for instance, constructs a sequence where every
element is the same.
```clojure
user=> (take 10 (repeat :hi))
(:hi :hi :hi :hi :hi :hi :hi :hi :hi :hi)
user=> (repeat 3 :echo)
(:echo :echo :echo)
```
And its close relative repeatedly simply calls a function (f) to generate an
infinite sequence of values, over and over again, without any relationship
between elements. For an infinite sequence of random numbers:
```clojure
user=> (rand)
0.9002678382322784
user=> (rand)
0.12375594203332863
user=> (take 3 (repeatedly rand))
(0.44442397843046755 0.33668691162169784 0.18244875487846746)
```
Notice that calling (rand) returns a different number each time. We say that
rand is an impure function, because it cannot simply be replaced by the same
value every time. It does something different each time it’s called.
There’s another very handy sequence function specifically for numbers: range,
which generates a sequence of numbers between two points. (range n) gives n
successive integers starting at 0. (range n m) returns integers from n to m-1.
(range n m step) returns integers from n to m, but separated by step.
```clojure
user=> (range 5)
(0 1 2 3 4)
user=> (range 2 10)
(2 3 4 5 6 7 8 9)
user=> (range 0 100 5)
(0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95)
```
To extend a sequence by repeating it forever, use cycle:
```clojure
user=> (take 10 (cycle [1 2 3]))
(1 2 3 1 2 3 1 2 3 1)
```
### Transforming sequences
Given a sequence, we often want to find a related sequence. map, for instance,
applies a function to each element–but has a few more tricks up its sleeve.
```clojure
user=> (map (fn [n vehicle] (str "I've got " n " " vehicle "s"))
[0 200 9]
["car" "train" "kiteboard"])
("I've got 0 cars" "I've got 200 trains" "I've got 9 kiteboards")
```
If given multiple sequences, map calls its function with one element from each
sequence in turn. So the first value will be (f 0 "car"), the second (f 200
"train"), and so on. Like a zipper, map folds together corresponding elements
from multiple collections. To sum three vectors, column-wise:
```clojure
user=> (map + [1 2 3]
[4 5 6]
[7 8 9])
(12 15 18)
```
If one sequence is bigger than another, map stops at the end of the smaller
one. We can exploit this to combine finite and infinite sequences. For example,
to number the elements in a vector:
```clojure
user=> (map (fn [index element] (str index ". " element))
(iterate inc 0)
["erlang" "ruby" "haskell"])
("0. erlang" "1. ruby" "2. haskell")
```
Transforming elements together with their indices is so common that Clojure has
a special function for it: map-indexed:
```clojure
user=> (map-indexed (fn [index element] (str index ". " element))
["erlang" "ruby" "haskell"])
("0. erlang" "1. ruby" "2. haskell")
```
You can also tack one sequence onto the end of another, like so:
```clojure
user=> (concat [1 2 3] [:a :b :c] [4 5 6])
(1 2 3 :a :b :c 4 5 6)
```
Another way to combine two sequences is to riffle them together, using
interleave.
```clojure
user=> (interleave [:a :b :c] [1 2 3])
(:a 1 :b 2 :c 3)
```
And if you want to insert a specific element between each successive pair in a
sequence, try interpose:
```clojure
user=> (interpose :and [1 2 3 4])
(1 :and 2 :and 3 :and 4)
```
To reverse a sequence, use reverse.
```clojure
user=> (reverse [1 2 3])
(3 2 1)
user=> (reverse "woolf")
(\f \l \o \o \w)
```
Strings are sequences too! Each element of a string is a character, written \f.
You can rejoin those characters into a string with apply str:
```clojure
user=> (apply str (reverse "woolf"))
"floow"
…and break strings up into sequences of chars with seq.
user=> (seq "sato")
(\s \a \t \o)
```
To randomize the order of a sequence, use shuffle.
```clojure
user=> (shuffle [1 2 3 4])
[3 1 2 4]
user=> (apply str (shuffle (seq "abracadabra")))
"acaadabrrab"
```
### Subsequences
We’ve already seen take, which selects the first n elements. There’s also drop,
which removes the first n elements.
```clojure
user=> (range 10)
(0 1 2 3 4 5 6 7 8 9)
user=> (take 3 (range 10))
(0 1 2)
user=> (drop 3 (range 10))
(3 4 5 6 7 8 9)
```
And for slicing apart the other end of the sequence, we have take-last and
drop-last:
```clojure
user=> (take-last 3 (range 10))
(7 8 9)
user=> (drop-last 3 (range 10))
(0 1 2 3 4 5 6)
```
take-while and drop-while work just like take and drop, but use a function to
decide when to cut.
```clojure
user=> (take-while pos? [3 2 1 0 -1 -2 10])
(3 2 1)
```
In general, one can cut a sequence in twain by using split-at, and giving it a
particular index. There’s also split-with, which uses a function to decide when
to cut.
```clojure
(split-at 4 (range 10))
[(0 1 2 3) (4 5 6 7 8 9)]
user=> (split-with number? [1 2 3 :mark 4 5 6 :mark 7])
[(1 2 3) (:mark 4 5 6 :mark 7)]
```
Notice that because indexes start at zero, sequence functions tend to have
predictable numbers of elements. (split-at 4) yields four elements in the first
collection, and ensures the second collection begins at index four. (range 10)
has ten elements, corresponding to the first ten indices in a sequence. (range
3 5) has two (since 5 - 3 is two) elements. These choices simplify the
definition of recursive functions as well.
We can select particular elements from a sequence by applying a function. To
find all positive numbers in a list, use filter:
```clojure
user=> (filter pos? [1 5 -4 -7 3 0])
(1 5 3)
```
filter looks at each element in turn, and includes it in the resulting sequence
only if (f element) returns a truthy value. Its complement is remove, which
only includes those elements where (f element) is false or nil.
```clojure
user=> (remove string? [1 "turing" :apple])
(1 :apple)
```
Finally, one can group a sequence into chunks using partition, partition-all,
or partition-by. For instance, one might group alternating values into pairs:
```clojure
user=> (partition 2 [:cats 5 :bats 27 :crocodiles 0])
((:cats 5) (:bats 27) (:crocodiles 0))
```
Or separate a series of numbers into negative and positive runs:
```clojure
(user=> (partition-by neg? [1 2 3 2 1 -1 -2 -3 -2 -1 1 2])
((1 2 3 2 1) (-1 -2 -3 -2 -1) (1 2))
```
### Collapsing sequences
After transforming a sequence, we often want to collapse it in some way; to
derive some smaller value. For instance, we might want the number of times each
element appears in a sequence:
```clojure
user=> (frequencies [:meow :mrrrow :meow :meow])
{:meow 3, :mrrrow 1}
```
Or to group elements by some function:
```clojure
user=> (pprint (group-by :first [{:first "Li" :last "Zhou"}
{:first "Sarah" :last "Lee"}
{:first "Sarah" :last "Dunn"}
{:first "Li" :last "O'Toole"}]))
{"Li" [{:last "Zhou", :first "Li"} {:last "O'Toole", :first "Li"}],
"Sarah" [{:last "Lee", :first "Sarah"} {:last "Dunn", :first "Sarah"}]}
```
Here we’ve taken a sequence of people with first and last names, and used the
:first keyword (which can act as a function!) to look up those first names.
group-by used that function to produce a map of first names to lists of
people–kind of like an index.
In general, we want to combine elements together in some way, using a function.
Where map treated each element independently, reducing a sequence requires that
we bring some information along. The most general way to collapse a sequence is
reduce.
```clojure
user=> (doc reduce)
-------------------------
clojure.core/reduce
([f coll] [f val coll])
f should be a function of 2 arguments. If val is not supplied,
returns the result of applying f to the first 2 items in coll, then
applying f to that result and the 3rd item, etc. If coll contains no
items, f must accept no arguments as well, and reduce returns the
result of calling f with no arguments. If coll has only 1 item, it
is returned and f is not called. If val is supplied, returns the
result of applying f to val and the first item in coll, then
applying f to that result and the 2nd item, etc. If coll contains no
items, returns val and f is not called.
```
That’s a little complicated, so we’ll start small. We need a function, f, which
combines successive elements of the sequence. (f state element) will return the
state for the next invocation of f. As f moves along the sequence, it carries
some changing state with it. The final state is the return value of reduce.
```clojure
user=> (reduce + [1 2 3 4])
10
```
reduce begins by calling (+ 1 2), which yields the state 3. Then it calls (+ 3
3), which yields 6. Then (+ 6 4), which returns 10. We’ve taken a function over
two elements, and used it to combine all the elements. Mathematically, we could
write:
```clojure
1 + 2 + 3 + 4
3 + 3 + 4
6 + 4
10
```
So another way to look at reduce is like sticking a function between each pair
of elements. To see the reducing process in action, we can use reductions,
which returns a sequence of all the intermediate states.
```clojure
user=> (reductions + [1 2 3 4])
(1 3 6 10)
```
Oftentimes we include a default state to start with. For instance, we could
start with an empty set, and add each element to it as we go along:
```clojure
user=> (reduce conj #{} [:a :b :b :b :a :a])
#{:a :b}
```
Reducing elements into a collection has its own name: into. We can conj [key
value] vectors into a map, for instance, or build up a list:
```clojure
user=> (into {} [[:a 2] [:b 3]])
{:a 2, :b 3}
user=> (into (list) [1 2 3 4])
(4 3 2 1)
```
Because elements added to a list appear at the beginning, not the end, this
expression reverses the sequence. Vectors conj onto the end, so to emit the
elements in order, using reduce, we might try:
```clojure
user=> (reduce conj [] [1 2 3 4 5])
(reduce conj [] [1 2 3 4 5])
[1 2 3 4 5]
```
Which brings up an interesting thought: this looks an awful lot like map. All
that’s missing is some kind of transformation applied to each element.
```clojure
(defn my-map [f coll]
(reduce (fn [output element]
(conj output (f element)))
[]
coll))
user=> (my-map inc [1 2 3 4])
[2 3 4 5]
```
Huh. map is just a special kind of reduce. What about, say, take-while?
```clojure
(defn my-take-while [f coll]
(reduce (fn [out elem]
(if (f elem)
(conj out elem)
(reduced out)))
[]
coll))
```
We’re using a special function here, reduced, to indicate that we’ve completed
our reduction early and can skip the rest of the sequence.
```clojure
user=> (my-take-while pos? [2 1 0 -1 0 1 2])
[2 1]
```
reduce really is the uberfunction over sequences. Almost any operation on a
sequence can be expressed in terms of a reduce–though for various reasons, many
of the Clojure sequence functions are not written this way. For instance,
take-while is actually defined like so:
```clojure
user=> (source take-while)
(defn take-while
"Returns a lazy sequence of successive items from coll while
(pred item) returns true. pred must be free of side-effects."
{:added "1.0"
:static true}
[pred coll]
(lazy-seq
(when-let [s (seq coll)]
(when (pred (first s))
(cons (first s) (take-while pred (rest s)))))))
```
There’s a few new pieces here, but the structure is essentially the same as our
initial attempt at writing map. When the predicate matches the first element,
cons the first element onto take-while, applied to the rest of the sequence.
That lazy-seq construct allows Clojure to compute this sequence as required,
instead of right away. It defers execution to a later time.
Most of Clojure’s sequence functions are lazy. They don’t do anything until
needed. For instance, we can increment every number from zero to infinity:
```clojure
user=> (def infseq (map inc (iterate inc 0)))
#'user/infseq
user=> (realized? infseq)
false
```
That function returned immediately. Because it hasn’t done any work yet, we say
the sequence is unrealized. It doesn’t increment any numbers at all until we
ask for them:
```clojure
user=> (take 10 infseq)
(1 2 3 4 5 6 7 8 9 10)
user=> (realized? infseq)
true
```
Lazy sequences also remember their contents, once evaluated, for faster access.
### Putting it all together
We’ve seen how recursion generalizes a function over one thing into a function
over many things, and discovered a rich landscape of recursive functions over
sequences. Now let’s use our knowledge of sequences to solve a more complex
problem: find the sum of the products of consecutive pairs of the first 1000
odd integers.
First, we’ll need the integers. We can start with 0, and work our way up to
infinity. To save time printing an infinite number of integers, we’ll start
with just the first 10.
```clojure
user=> (take 10 (iterate inc 0))
(0 1 2 3 4 5 6 7 8 9)
```
Now we need to find only the ones which are odd. Remember, filter pares down a
sequence to only those elements which pass a test.
```clojure
user=> (take 10 (filter odd? (iterate inc 0)))
(1 3 5 7 9 11 13 15 17 19)
```
For consecutive pairs, we want to take [1 3 5 7 ...] and find a sequence like
([1 3] [3 5] [5 7] ...). That sounds like a job for partition:
```clojure
user=> (take 3 (partition 2 (filter odd? (iterate inc 0))))
((1 3) (5 7) (9 11))
```
Not quite right–this gave us non-overlapping pairs, but we wanted overlapping
ones too. A quick check of (doc partition) reveals the step parameter:
```clojure
user=> (take 3 (partition 2 1 (filter odd? (iterate inc 0))))
((1 3) (3 5) (5 7))
```
Now we need to find the product for each pair. Given a pair, multiply the two
pieces together… yes, that sounds like map:
```clojure
user=> (take 3 (map (fn [pair] (* (first pair) (second pair)))
(partition 2 1 (filter odd? (iterate inc 0)))))
(3 15 35)
```
Getting a bit unwieldy, isn’t it? Only one final step: sum all those products.
We’ll adjust the take to include the first 1000, not the first 3, elements.
```clojure
user=> (reduce +
(take 1000
(map (fn [pair] (* (first pair) (second pair)))
(partition 2 1
(filter odd?
(iterate inc 0)))))
1335333000
```
The sum of the first thousand products of consecutive pairs of the odd integers
starting at 0. See how each part leads to the next? This expression looks a lot
like the way we phrased the problem in English–but both English and Lisp
expressions are sort of backwards, in a way. The part that happens first
appears deepest, last, in the expression. In a chain of reasoning like this,
it’d be nicer to write it in order.
```clojure
user=> (->> 0
(iterate inc)
(filter odd?)
(partition 2 1)
(map (fn [pair]
(* (first pair) (second pair))))
(take 1000)
(reduce +))
1335333000
```
Much easier to read: now everything flows in order, from top to bottom, and
we’ve flattened out the deeply nested expressions into a single level. This is
how object-oriented languages structure their expressions: as a chain of
function invocations, each acting on the previous value.
But how is this possible? Which expression gets evaluated first? (take 1000)
isn’t even a valid call–where’s its second argument? How are any of these forms
evaluated?
What kind of arcane function is ->>?
All these mysteries, and more, in Chapter 5: Macros.
### Problems
1. Write a function to find out if a string is a palindrome–that is, if it
looks the same forwards and backwards.
2. Find the number of ‘c’s in “abracadabra”.
3. Write your own version of filter.
4. Find the first 100 prime numbers: 2, 3, 5, 7, 11, 13, 17, ….
## Macros
In Chapter 1, I asserted that the grammar of Lisp is uniform: every expression
is a list, beginning with a verb, and followed by some arguments. Evaluation
proceeds from left to right, and every element of the list must be evaluated
before evaluating the list itself. Yet we just saw, at the end of Sequences, an
expression which seemed to violate these rules.
Clearly, this is not the whole story.
### Macroexpansion
There is another phase to evaluating an expression; one which takes place
before the rules we’ve followed so far. That process is called macro-expansion.
During macro-expansion, the code itself is restructured according to some set
of rules–rules which you, the programmer, can define.
```clojure
(defmacro ignore
"Cancels the evaluation of an expression, returning nil instead."
[expr]
nil)
user=> (ignore (+ 1 2))
nil
```
defmacro looks a lot like defn: it has a name, an optional documentation
string, an argument vector, and a body–in this case, just nil. In this case, it
looks like it simply ignored the expr (+ 1 2) and returned nil–but it’s
actually deeper than that. (+ 1 2) was never evaluated at all.
```clojure
user=> (def x 1)
#'user/x
user=> x
1
user=> (ignore (def x 2))
nil
user=> x
1
```
def should have defined x to be 2 no matter what–but that never happened. At
macroexpansion time, the expression (ignore (+ 1 2)) was replaced by the
expression nil, which was then evaluated to nil. Where functions rewrite
values, macros rewrite code.
To see these different layers in play, let’s try a macro which reverses the
order of arguments to a function.
```clojure
(defmacro rev [fun & args]
(cons fun (reverse args)))
```
This macro, named rev, takes one mandatory argument: a function. Then it takes
any number of arguments, which are collected in the list args. It constructs a
new list, starting with the function, and followed by the arguments, in reverse
order.
First, we macro-expand:
```clojure
user=> (macroexpand '(rev str "hi" (+ 1 2)))
(str (+ 1 2) "hi")
```
So the rev macro took str as the function, and "hi" and (+ 1 2) as the
arguments; then constructed a new list with the same function, but the
arguments reversed. When we evaluate that expression, we get:
```clojure
user=> (eval (macroexpand '(rev str "hi" (+ 1 2))))
"3hi"
```
macroexpand takes an expression and returns that expression with all macros
expanded. eval takes an expression and evaluates it. When you type an unquoted
expression into the REPL, Clojure macroexpands, then evaluates. Two stages–the
first transforming code, the second transforming values.
### Across languages
Some languages have a metalanguage: a language for extending the language
itself. In C, for example, macros are implemented by the C preprocessor, which
has its own syntax for defining expressions, matching patterns in the source
code’s text, and replacing that text with other text. But that preprocessor is
not C–it is a separate language entirely, with special limitations. In Clojure,
the metalanguage is Clojure itself–the full power of the language is available
to restructure programs. This is called a procedural macro system. Some Lisps,
like Scheme, use a macro system based on templating expressions, and still
others use more powerful models like f-expressions–but that’s a discussion for
a later time.
There is another key difference between Lisp macros and many other macro
systems: in Lisp, the macros operate on expressions: the data structure of the
code itself. Because Lisp code is written explicitly as a data structure, a
tree made out of lists, this transformation is natural. You can see the
structure of the code, which makes it easy to reason about its transformation.
In the C preprocessor, macros operate only on text: there is no understanding
of the underlying syntax. Even in languages like Scala which have syntactic
macros, the fact that the code looks nothing like the syntax tree makes it
cumbersome to truly restructure expressions.
When people say that Lisp’s syntax is “more elegant”, or “more beautiful”, or
“simpler”, this is part of what they they mean. By choosing to represent the
program directly as a a data structure, we make it much easier to define
complex transformations of code itself.
### Defining new syntax
What kind of transformations are best expressed with macros?
Most languages encode special syntactic forms–things like “define a function”,
“call a function”, “define a local variable”, “if this, then that”, and so on.
In Clojure, these are called special forms. if is a special form, for instance.
Its definition is built into the language core itself; it cannot be reduced
into smaller parts.
```clojure
(if (< 3 x)
"big"
"small")
```
Or in Javascript:
```clojure
if (3 < x) {
return "big";
} else {
return "small";
}
```
In Javascript, Ruby, and many other languages, these special forms are fixed.
You cannot define your own syntax. For instance, one cannot define or in a
language like JS or Ruby: it must be defined for you by the language author.
In Clojure, or is just a macro.
```clojure
user=> (source or)
(defmacro or
"Evaluates exprs one at a time, from left to right. If a form
returns a logical true value, or returns that value and doesn't
evaluate any of the other expressions, otherwise it returns the
value of the last expression. (or) returns nil."
{:added "1.0"}
([] nil)
([x] x)
([x & next]
`(let [or# ~x]
(if or# or# (or ~@next)))))
nil
```
That ` operator–that’s called syntax-quote. It works just like regular
quote–preventing evaluation of the following list–but with a twist: we can
escape the quoting rule and substitute in regularly evaluated expressions using
unquote (~), and unquote-splice (~@). Think of a syntax-quoted expression like
a template for code, with some parts filled in by evaluated forms.
```clojure
user=> (let [x 2] `(inc x))
(clojure.core/inc user/x)
user=> (let [x 2] `(inc ~x))
(clojure.core/inc 2)
```
See the difference? ~x substitutes the value of x, instead of using x as an
unevaluated symbol. This code is essentially just shorthand for something like
```clojure
user=> (let [x 2] (list 'clojure.core/inc x))
(inc 2)
```
… where we explicitly constructed a new list with the quoted symbol 'inc and
the current value of x. Syntax quote just makes it easier to read the code,
since the quoted and expanded expressions have similar shapes.
The ~@ unquote splice works just like ~, except it explodes a list into
multiple expressions in the resulting form:
```clojure
user=> `(foo ~[1 2 3])
(user/foo [1 2 3])
user=> `(foo ~@[1 2 3])
(user/foo 1 2 3)
```
~@ is particularly useful when a function or macro takes an arbitrary number of
arguments. In the definition of or, it’s used to expand (or a b c) recursively.
```clojure
user=> (pprint (macroexpand '(or a b c d)))
(let*
[or__3943__auto__ a]
(if or__3943__auto__ or__3943__auto__ (clojure.core/or b c d)))
```
We’re using pprint (for “pretty print”) to make this expression easier to read.
(or a b c d) is defined in terms of if: if the first element is truthy we
return it; otherwise we evaluate (or b c d) instead, and so on.
The final piece of the puzzle here is that weirdly named symbol:
or__3943__auto__. That variable was automatically generated by Clojure, to
prevent conflicts with an existing variable name. Because macros rewrite code,
they have to be careful not to interfere with local variables, or it could get
very confusing. Whenever we need a new variable in a macro, we use gensym to
generate a new symbol.
```clojure
user=> (gensym "hi")
hi326
user=> (gensym "hi")
hi329
user=> (gensym "hi")
hi332
```
Each symbol is different! If we tack on a # to the end of a symbol in a
syntax-quoted expression, it’ll be expanded to a particular gensym:
```clojure
user=> `(let [x# 2] x#)
(clojure.core/let [x__339__auto__ 2] x__339__auto__)
```
Note that you can always escape this safety feature if you want to override
local variables. That’s called symbol capture, or an anaphoric or unhygenic
macro. To override local symbols, just use ~'foo instead of foo#.
With all the pieces on the board, let’s compare the or macro and its expansion:
```clojure
(defmacro or
"Evaluates exprs one at a time, from left to right. If a form
returns a logical true value, or returns that value and doesn't
evaluate any of the other expressions, otherwise it returns the
value of the last expression. (or) returns nil."
{:added "1.0"}
([] nil)
([x] x)
([x & next]
`(let [or# ~x]
(if or# or# (or ~@next)))))
user=> (pprint (clojure.walk/macroexpand-all
'(or (mossy? stone) (cool? stone) (wet? stone))))
(let*
[or__3943__auto__ (mossy? stone)]
(if
or__3943__auto__
or__3943__auto__
(let*
[or__3943__auto__ (cool? stone)]
(if or__3943__auto__ or__3943__auto__ (wet? stone)))))
```
See how the macro’s syntax-quoted (let ... has the same shape as the resulting
code? or# is expanded to a variable named or__3943__auto__, which is bound to
the expression (mossy? stone). If that variable is truthy, we return it.
Otherwise, we (and here’s the recursive part) rebind or__3943__auto__ to (cool?
stone) and try again. If that fails, we fall back to evaluating (wet?
stone)–thanks to the base case, the single-argument form of the or macro.
### Control flow
We’ve seen that or is a macro written in terms of the special form if–and
because of the way the macro is structured, it does not obey the normal
execution order. In (or a b c), only a is evaluated first–then, only if it is
false or nil, do we evaluate b. This is called short-circuiting, and it works
for and as well.
Changing the order of evaluation in a language is called control flow, and lets
programs make decisions based on varying circumstances. We’ve already seen if:
```clojure
user=> (if (= 2 2) :a :b)
:a
```
if takes a predicate and two expressions, and only evaluates one of them,
depending on whether the predicate evaluates to a truthy or falsey value.
Sometimes you want to evaluate more than one expression in order. For this, we
have do.
```clojure
user=> (if (pos? -5)
(prn "-5 is positive")
(do
(prn "-5 is negative")
(prn "Who would have thought?")))
"-5 is negative"
"Who would have thought?"
nil
```
prn is a function which has a side effect: it prints a message to the screen,
and returns nil. We wanted to print two messages, but if only takes a single
expression per branch–so in our false branch, we used do to wrap up two prns
into a single expression, and evaluate them in order. do returns the value of
the final expression, which happens to be nil here.
When you only want to take one branch of an if, you can use when:
```clojure
user=> (when false
(prn :hi)
(prn :there))
nil
user=> (when true
(prn :hi)
(prn :there))
:hi
:there
nil
```
Because there is only one path to take, when takes any number of expressions,
and evaluates them only when the predicate is truthy. If the predicate
evaluates to nil or false, when does not evaluate its body, and returns nil.
Both when and if have complementary forms, when-not and if-not, which simply
invert the sense of their predicate.
```clojure
user=> (when-not (number? "a string")
:here)
:here
user=> (if-not (vector? (list 1 2 3))
:a
:b)
:a
```
Often, you want to perform some operation, and if it’s truthy, re-use that
value without recomputing it. For this, we have when-let and if-let. These work
just like when and let combined.
```clojure
user=> (when-let [x (+ 1 2 3 4)]
(str x))
"10"
user=> (when-let [x (first [])]
(str x))
nil
```
while evaluates an expression so long as its predicate is truthy. This is
generally useful only for side effects, like prn or def; things that change the
state of the world.
```clojure
user=> (def x 0)
#'user/x
user=> (while (< x 5)
#_=> (prn x)
#_=> (def x (inc x)))
0
1
2
3
4
nil
```
cond (for “conditional”) is like a multiheaded if: it takes any number of
test/expression pairs, and tries each test in turn. The first test which
evaluates truthy causes the following expression to be evaluated; then cond
returns that expression’s value.
```clojure
user=> (cond
#_=> (= 2 5) :nope
#_=> (= 3 3) :yep
#_=> (= 5 5) :cant-get-here
#_=> :else :a-default-value)
:yep
```
If you find yourself making several similar decisions based on a value, try
condp, for “cond with predicate”. For instance, we might categorize a number
based on some ranges:
```clojure
(defn category
"Determines the Saffir-Simpson category of a hurricane, by wind speed in meters/sec"
[wind-speed]
(condp <= wind-speed
70 :F5
58 :F4
49 :F3
42 :F2
:F1)) ; Default value
user=> (category 10)
:F1
user=> (category 50)
:F3
user=> (category 100)
:F5
```
condp generates code which combines the predicate <= with each number, and the
value of wind-speed, like so:
```clojure
(if (<= 70 wind-speed) :F5
(if (<= 58 wind-speed) :F4
(if (<= 49 wind-speed) :F3
(if (<= 42 wind-speed) :F2
:F1))))
```
Specialized macros like condp are less commonly used than if or when, but they
still play an important role in simplifying repeated code. They clarify the
meaning of complex expressions, making them easier to read and maintain.
Finally, there’s case, which works a little bit like a map of keys to
values–only the values are code, to be evaluated. You can think of case like
(condp = ...), trying to match an expression to a particular branch for which
it is equal.
```clojure
(defn with-tax
"Computes the total cost, with tax, of a purchase in the given state."
[state subtotal]
(case state
:WA (* 1