Special Forms

Special forms are Clojure’s primitive building blocks of
computation, on top of which all the rest of Clojure is built. This
foundation shares a lineage with the earliest Lisps, which also defined a limited set of primitives that define
the fundamental operations of the runtime, and are taken as sufficient to
describe any possible computation.[19] Further, special forms have their own syntax (e.g., many do
not take arguments per se) and evaluation semantics.

As you’ve seen, things that are often described as primitive
operations or statements in most languages—including control forms like
when and operators like addition and
negation—are not primitives in Clojure. Rather, everything that isn’t a
special form is implemented in Clojure itself by bootstrapping from that
limited set of primitive operations.[20] The practical effect of this is that, if Clojure doesn’t
provide a language construct that you want or need, you can likely build
it yourself.[21]

Though all of Clojure is built on top of its special forms, you need
to understand what each one does—as you’ll use many of them constantly.
Let’s now discuss each one in turn.

Suppressing Evaluation: quote

quotesuppresses evaluation of a Clojure expression. The most
obvious impact of this relates to symbols, which, if they name a var,
evaluate to that var’s value. With quote, evaluation is suppressed, so symbols
evaluate to themselves (just like strings, numbers, and so on):

(quote x)
;= x
(symbol? (quote x))
;= true

There is reader syntax for quote; prefixing any form with a quote
character (') will expand into a
usage of quote:

'x
;= x

Any Clojure form can be quoted, including data structures. Doing
so returns the data structure in question, with evaluation recursively
suppressed for all of its elements:

'(+ x x)
;= (+ x x)
(list? '(+ x x))
;= true

While lists are usually evaluated as calls, quoting a list suppresses
that evaluation, yielding the list itself; in this case, a list of three
symbols: '+, 'x, and 'x.
Note that this is exactly what we get if we “manually” construct the
list without using a list literal:

(list '+ 'x 'x)
;= (+ x x)

Tip

You can usually have a peek at what the reader produces by
quoting a form. Let’s go meta for a moment and try it first on quote
itself:

Code Blocks: do

doevaluates all of the expressions provided to it in order and yields the last expression’s
value as its value. For example:

(do
(println "hi")
(apply * [4 5 6]))
; hi
;= 120

The values of all but the last expression are discarded, although
their side effects do occur (such as printing to standard out as we’re
doing here, or manipulations of a stateful object available in the
current scope).

Note that many other forms (including fn, let,
loop, and try—and any derivative of these, such as
defn) wrap their bodies in an
implicit do expression, so that multiple inner expressions can be evaluated. For
example, let expressions—like this
one that defines two locals—provide an implicit do context to their bodies:

This allows any number of expressions to be evaluated within the
context of the let form, with only
the final one determining its ultimate result. If let didn’t wrap its body with a do form, you would have to add it
explicitly:[22]

Defining Vars: def

We’ve already seen def
in action;[23] it defines (or redefines) a var (with an optional value)
within the current namespace:

(def p "foo")
;= #'user/p
p
;= "foo"

Many other forms implicitly create or redefine vars, and therefore
use def internally. It is customary
for such forms to be prefixed with “def,” such as defn, defn-, defprotocol, defonce, defmacro, and so on.

Warning

Although forms that create or redefine vars have names that
start with “def,” unfortunately not all forms that start with “def”
create or redefine vars. Examples of the latter include deftype, defrecord, and defmethod.

Local Bindings: let

letallows you to define named references that are lexically
scoped to the extent of the let
expression. Said another way, let
defines locals. For example, this rudimentary static method in
Java:

The x2 and y2 locals in the respective function/method
bodies serve the same purpose: to establish a named, scoped reference to
an intermediate value.

Note

There are many terms used to talk about named references
established by let in Clojure
parlance:

locals

local bindings

particular values are said to be
let-bound

Bindings and bound
used in connection with let are
entirely distinct from the binding
macro, which controls scoped thread-local variables; see Dynamic Scope for more about the
latter.

Note that let is implicitly
used anywhere locals are required. In particular, fn (and therefore all other function-creation
and function-definition forms like defn) uses let to bind function parameters as locals
within the scope of the function being defined. For example, x and y in
the hypot function above are
let-bound by defn. So, the vector
that defines the set of bindings for a let scope obeys the same semantics whether it
is used to define function parameters or an auxiliary local binding
scope.

Note

Occasionally, you will want evaluate an expression in the
binding vector provided to let, but
have no need to refer to its result within the context of the let’s body. In these cases, it is customary
to use an underscore as the bound name for such values, so that readers of
the code will know that results of such expressions are going unused
intentionally.

This is only ever relevant when the expression in question is
side-effecting; a common example
would be printing some intermediate value:

Here we’re retrieving our current latitude and longitude using a
hypothetical API, and we’d like to print that out before converting
the location data to a human-recognizable city name. We might want to
rebind the same name a couple of times in the course of the let’s binding vector, paving over those
intermediate values. To print out that intermediate value, we add it
to the binding vector prior to rebinding its name, but we indicate
that we are intentionally ignoring the return value of that expression
by naming it _.

let has two particular semantic
wrinkles that are very different from locals you may be used to in other
languages:

All locals are immutable. You can
override a local binding within a nested let form or a later binding of the same
name within the same binding vector, but there is no way to bash out
a bound name and change its value within the scope of a single
let form. This eliminates a
source of common errors and bugs without sacrificing
capability:

The loop and recur special forms provide for looping cases where
values need to change on each cycle of a loop; see Looping: loop and recur.

If you really need a “mutable” local binding, Clojure
provides a raft of reference types that enforce specific mutation semantics; see
Clojure Reference Types.

let’s binding vector is
interpreted at compile time to provide optional
destructuring of common collection types. Destructuring can aid
substantially in eliminating certain types of verbose (and frankly,
dull) code often associated with working with collections provided
as arguments to functions.

Destructuring (let, Part 2)

A lot of Clojure programming involves working with various
implementations of data structure abstractions,
sequential and map collections being two of those key abstractions. Many Clojure functions
accept and return seqs and maps generally—rather than specific
implementations—and most Clojure libraries and applications are built up
relying upon these abstractions instead of particular concrete structures, classes, and so
on. This allows functions and libraries to be trivially composed around
the data being handled with a minimum of integration, “glue code,” and
other incidental complexity.

One challenge when working with abstract collections is being able
to concisely access multiple values in those collections. For example,
here’s a collection, a Clojure vector:

(def v [42 "foo" 99.2 [5 12]])
;= #'user/v

Consider a couple of approaches for accessing the values in our
sample vector:

Clojure provides convenience functions for accessing the first, second, and last values from a sequential
collection.

The nth function allows you
pluck any value from a sequential collection using an index into
that collection.

Vectors are functions of their indices.

All of Clojure’s sequential collections implement the java.util.List interface, so you can use that interface’s .get method to access their
contents.

All of these are perfectly fine ways to access a single
“top-level” value in a vector, but things start getting more complex if
we need to access multiple values to perform some operation:

(+ (first v) (v 2))
;= 141.2

Or if we need to access values in nested collections:

(+ (first v) (first (last v)))
;= 47

Clojure destructuring provides a concise syntax for declaratively pulling apart
collections and binding values contained therein as named locals within
a let form. And, because
destructuring is a facility provided by let, it can be used in any expression that
implicitly uses let (like fn, defn,
loop, and so on).

There are two flavors of destructuring: one that operates over
sequential collections, and another that works with maps.

Sequential destructuring

Sequential destructuring works with any sequential
collection, including:

Clojure lists, vectors, and seqs

Any collection that implements java.util.List (like ArrayLists and LinkedLists)

Java arrays

Strings, which are destructured into their characters

Here’s a basic example, where we are destructuring the same
value v discussed above:

In its simplest form, the vector provided to let contains pairs of names and values, but
here we’re providing a vector of symbols—[x y
z]—instead of a scalar symbol name. What this does is cause
the value v to be destructured
sequentially, with the first value bound to x within the body of the let form, the second value bound to y, and the third value bound to z. We can then use those destructured locals
like any other locals. This is equivalent to:

(let [x (nth v 0)
y (nth v 1)
z (nth v 2)]
(+ x z))
;= 141.2

Note

Python has something similar to Clojure’s sequential
destructuring, called unpacking. The equivalent to the preceding code snippet in
Python would be something like:

Clojure, Python, and Ruby all seem pretty similar on their
face; but, as you’ll see as we go along, Clojure goes quite a long
ways beyond what Python and Ruby offer.

Destructuring forms are intended to mirror the structure of the
collection that is being bound.[24] So, we can line up our destructuring form with the
collection being destructured and get a very accurate notion of which
values are going to be bound to which names:[25]

[x y z]
[42 "foo" 99.2 [5 12]]

Destructuring forms can be composed as well, so we can dig into
the nested vector in v with
ease:[26]

(let [[x _ _ [y z]] v]
(+ x y z))
;= 59

If we visually line up our destructuring form and the source
vector again, the work being done by that form should again be very
clear:

[x _ _ [y z ]]
[42 "foo" 99.2 [5 12]]

Warning

If our nested vector had a vector inside of it, we could destructure it as
well. The destructuring mechanism has no limit to how far it can
descend into a deeply nested data structure, but there are limits to
good taste. If you’re using destructuring to pull values out of a
collection four or more levels down, chances are your destructuring
form will be difficult to interpret for the next person to see that
code—even if that next person is you!

There are two additional features of sequential destructuring
forms you should know about:

Gathering extra-positional sequential values

You can use &to gather values that lay beyond the positions
you’ve named in your destructuring form into a sequence; this
is similar to the mechanism underlying varargs in Java methods
and is the basis of rest
arguments in Clojure functions:

(let [[x & rest] v]
rest)
;= ("foo" 99.2 [5 12])

This is particularly useful when processing
items from a sequence, either via recursive function calls or
in conjunction with a loop
form. Notice that the value of rest here is a sequence, and
not a vector, even though we provided a
vector to the destructuring form.

Retaining the destructured value

You can establish a local binding for the original collection being destructured
by specifying the name it should have via the :as option within the destructuring
form:

Here, original-vector is bound to the
unchanged value of v. This
comes in handy when you are destructuring a collection that is
the result of a function call, but you need to retain a
reference to that unaltered result in addition to having the
benefit of destructuring it. Without this feature, doing so
would require something like this:

Here we’re binding the value for :a in the map to a, and the value for :b in the map to b. Going back to our visual alignment of the
destructuring form with the (in this case, partial) collection being
destructured, we can again see the structural correspondence:

{a :a b :b}
{:a 5 :b 6}

Note that there is no requirement that the keys used for map lookups in destructuring be keywords; any
type of value may be used for lookup:

(let [{f "foo"} m]
(+ f 12))
;= 100
(let [{v 42} m]
(if v 1 0))
;= 0

Indices into vectors, strings, and arrays can be used as keys in
a map destructuring form.[28] One place where this can be helpful is if you are
representing matrices by using vectors, but only need a couple of values from
one. Using map destructuring to pull out two or three values from a
3×3 matrix can be much easier than using a potentially nine-element
sequential destructuring form:

(let [{x 3 y 8} [12 0 0 -18 44 6 0 0 1]]
(+ x y))
;= -17

Just as sequential destructuring forms could be composed, so can
the map variety:

(let [{{e :e} :d} m]
(* 2 e))
;= 20

The outer map destructuring—{{e :e} :d}—is acting
upon the top-level source collection m to pull out the value mapped to :d. The inner map destructuring—{e :e}—is acting on
the value mapped to :d to pull out
its value for :e.

The coup de grâce is the composition of
both map and sequential destructuring, however they are needed to
effectively extract the values you need from the collections at
hand:

Retaining the destructured value. Just like sequential destructuring, adding an :as pair to the destructuring form to hold a reference to
the source collection, which you can use like any other let-bound value:

Default values. You can use an :or pair to provide a defaults map; if a key specified in
the destructuring form is not available in the source collection,
then the defaults map will be consulted:

(let [{k :unknown x :a
:or {k 50}} m]
(+ k x))
;= 55

This allows you to avoid either merging the source map into a
defaults map ahead of its destructuring, or manually setting defaults
on destructured bindings that have nil values in the source collection, which
would get very tiresome beyond one or two
bindings with desired default values:

(let [{k :unknown x :a} m
k (or k 50)]
(+ k x))
;= 55

Furthermore, and unlike the code in the above example, :or knows the difference between no value
and a false (nil or false) value:

Binding values to their keys’ names. There are often stable names for various values in
maps, and it’s often desirable to bind those values by using the
same names in the scope of the let form as they are mapped to in the
source map. However, doing this using “vanilla” map destructuring
can get very repetitive:

(def chas {:name "Chas" :age 31 :location "Massachusetts"})
;= #'user/chas
(let [{name :name age :age location :location} chas]
(format "%s is %s years old and lives in %s." name age location))
;= "Chas is 31 years old and lives in Massachusetts."

Having to type the content of each key twice is decidedly
contrary to the spirit of destructuring’s concision. In such cases,
you can use the :keys, :strs, and :syms options to specify keyword, string,
and symbol keys (respectively) into the source map and the names the
corresponding values should be bound to in the let form without repetition. Our sample map
uses keywords for keys, so we’ll use :keys for it:

(let [{:keys [name age location]} chas]
(format "%s is %s years old and lives in %s." name age location))
;= "Chas is 31 years old and lives in Massachusetts."

…and switch to using :strs or
:syms when we know that the source
collection is using strings or symbols for keys:

(def brian {"name" "Brian" "age" 31 "location" "British Columbia"})
;= #'user/brian
(let [{:strs [name age location]} brian]
(format "%s is %s years old and lives in %s." name age location))
;= "Brian is 31 years old and lives in British Columbia."
(def christophe {'name "Christophe" 'age 33 'location "Rhône-Alpes"})
;= #'user/christophe
(let [{:syms [name age location]} christophe]
(format "%s is %s years old and lives in %s." name age location))
;= "Christophe is 31 years old and lives in Rhône-Alpes."

You will likely find yourself using :keys more than :strs or :syms; keyword keys are by far the most
common key type in Clojure maps and keyword arguments, and are the
general-purpose accessor by dint of their usage in conjunction with
records.

Destructuring rest sequences as map key/value pairs. We’ve already seen how extra-positional values in
sequential destructuring forms can be gathered into a “rest” seq,
and map and sequential destructuring can be composed as needed to
drill into any given data structure. Here’s a simple case of a
vector that contains some positional values, followed by a set of
key/value pairs:

We can destructure the original vector into its positional
elements, gathering the remainder into a rest seq.

That rest seq, consisting of alternating keys and values,
can be used as the basis for creating a new hashmap, which we can
then destructure as we wish.

However, “tolerable” isn’t a very high bar given the prevalence
of sequences of key/value pairs in programming. A better alternative
is a special variety of the compositional behavior offered by let’s destructuring forms: map destructuring
of rest seqs. If a rest seq has an even number of values—semantically,
key/value pairs—then it can be destructured as a map of those
key/value pairs instead of sequentially:

That is a far cleaner notation for doing exactly the same work
as us manually building a hash-map
out of the rest seq and destructuring that map, and is the basis of
Clojure functions’ optional keyword arguments described in “Keyword arguments”.

Creating Functions: fn

Functions are first-class values in Clojure; creating them
falls to the fn special form, which
also folds in the semantics of let
and do.

Here is a simple function that adds 10 to the number provided as an
argument:

(fn [x]
(+ 10 x))

fn accepts a let-style binding vector that defines the
names and numbers of arguments accepted by the function; the same
optional destructuring forms discussed in Destructuring (let, Part 2) can be applied to each argument
here.

The forms following the binding vector constitute the
body of the function. This body is placed in an
implicit do form, so each
function’s body may contain any number of forms; as with do, the last form in the body supplies the
result of the function call that is returned to the caller.

The arguments to a function are matched to each name or
destructuring form based on their positions in the calling form. So in
this call:

((fn [x] (+ 10 x)) 8)
;= 18

8 is the sole argument to the
function, and it is bound to the name x within the body of the function. This makes
the function call the equivalent of this let form:

(let [x 8]
(+ 10 x))

You can define functions that accept multiple arguments:

((fn [x y z] (+ x y z))
3 4 12)
;= 19

In this case, the function call is the equivalent of this let form:

(let [x 3
y 4
z 12]
(+ x y z))

Functions with multiple arities can be created as well; here, we’ll put the function in a
var so we can call it multiple times
by only referring to the var’s
name:

When defining a function with multiple arities, each arity’s
binding vector and implementation body must be enclosed within a pair of
parentheses. Function calls dispatch based on argument count; the proper
arity is selected based on the number of arguments that we provide in
our call.

In this last example, notice the optional name that we’ve given to
the function, adder-self-reference.
This optional first argument to fn
can be used within the function’s bodies to refer to itself—in this
case, so that the single-argument arity can call the two-argument arity
with a default second argument without referring to or requiring any
containing var.

Mutually recursive functions with letfn

Named fns (like the
above adder-self-reference) allow
you to easily create self-recursive functions. What is more tricky is
to create mutually recursive functions.

For such rare cases, there is the letfn special form, which allows you to
define several named functions at once, and all these functions will
know each other. Consider these naive reimplementations of odd? and even?:

The vector consists of several regular fn bodies, only the fn symbol is missing.

defn builds on fn. We’ve already seen defn used before, and the example above
should look familiar; defn is a
macro that encapsulates the functionality of def and fn so that you can concisely define
functions that are named and registered in the current namespace with
a given name. For example, these two definitions are
equivalent:

We’ll largely use defn forms to
illustrate fn forms for the rest of
this section, simply because calling functions bound to named vars is
easier to read than continually defining the functions to be called
inline.

Destructuring function arguments

defnsupports the destructuring of function arguments thanks
to it reusing let for binding
function arguments for the scope of a function’s body. You should
refer to the prior comprehensive discussion of destructuring to remind
yourself of the full range of options available; here, we’ll discuss
just a couple of destructuring idioms that are particularly common in
conjunction with functions.

Variadic functions. Functions can optionally gather all additional
arguments used in calls to it into a seq; this uses the same
mechanism as sequential destructuring does when gathering additional
values into a seq. Such functions are called
variadic, with the gathered arguments usually
called rest arguments or varargs. Here’s a function
that accepts one named positional argument, but gathers all
additional arguments into a remainder seq:

The seq formed for the rest arguments can be destructured just
like any other sequence; here we’re destructuring rest arguments to
make a function behave as if it had an explicitly defined zero-arg
arity:

Keyword arguments. It is often the case that you would like to define a
function that can accept many arguments, some of which might be
optional and some of which might have defaults. Further, you would
often like to avoid forcing a particular argument ordering upon
callers.[29]

fn (and therefore defn) provides support for such use cases
through keyword arguments, which is an idiom
built on top of the map
destructuring of rest sequences that let provides. Keyword arguments are pairs of
keywords and values appended to any strictly positional arguments in a
function call, and if the function was defined to accept keyword
arguments, those keyword/value pairs will be gathered into a map and
destructured by the function’s map destructuring form that is placed
in the same position as the rest
arguments seq:

The make-user function
strictly requires only one argument, a username. The rest of the
arguments are assumed to be keyword/value pairs, gathered into a
map, and then destructured using the map destructuring form
following &.

In the map destructuring form, we define a default of “now”
for the join-date value.

Calling make-user with a
single argument returns the user map, populated with defaulted
join- and expiration-date values and a nil email value since none was provided
in the keyword arguments.

Additional arguments provided to make-user are interpreted by the keyword
destructuring map, without consideration of their order.

Note

Because keyword arguments are built using let’s map destructuring, there’s nothing
stopping you from destructuring the rest argument map using types of
key values besides keywords (such as strings or numbers or even
collections). For example:

That said, we’ve never actually seen non-keyword key types
used in named function arguments. Keywords are overwhelmingly the
most common argument key type used, thus the use of
keyword arguments to describe the idiom.

Pre- and postconditions. fn provides support for
pre- and postconditions for performing assertions with function arguments and
return values. They are valuable features when testing and for
generally enforcing function invariants; we discuss them in Preconditions and Postconditions.

Function literals

We mentioned function literals briefly in Miscellaneous Reader Sugar. Equivalent to blocks in Ruby and lambdas
in Python, Clojure function literals’ role is
straightforward: when you need to define an anonymous
function—especially a very simple function—they provide the most
concise syntax for doing so.

For example, these anonymous function expressions are
equivalent:

(fn [x y] (Math/pow x y))
#(Math/pow %1 %2)

The latter is simply some reader sugar that is expanded into the
former; we can clearly see this by checking the result of reading the
textual code:[30]

The differences between the fn form and the shorter function literal
are:

No implicit do form. “Regular” fn forms (and all
of their derivatives) wrap their function bodies in an implicit
do form, as we discussed in Creating Functions: fn. This allows you to do things
like:

(fn [x y]
(println (str x \^ y))
(Math/pow x y))

The equivalent function literal requires an explicit do form:

#(do (println (str %1 \^ %2))
(Math/pow %1 %2))

Arity and arguments specified using unnamed positional
symbols. The fn examples above use
the named symbols x and y to specify both the arity of the function being defined, as well as the names of
the arguments passed to the function at runtime. In contrast, the
literal uses unnamed positional %
symbols, where %1 is the first
argument, %2 is the second
argument, and so on. In addition, the highest positional symbol
defines the arity of the function, so if we wanted to define a
function that accepted four arguments, we need only to refer to
%4 within the function literal’s
body.

There are two additional wrinkles to defining arguments in
function literals:

Function literals that accept a single argument are so
common that you can refer to the first argument to the function by
just using %. So, #(Math/pow % %2) is equivalent to
#(Math/pow %1 %2). You should
prefer the shorter notation in general.

You can define a variadic function[31] and refer to that function’s rest arguments using
the %& symbol. These
functions are therefore equivalent:

(fn [x & rest]
(- x (apply + rest)))
#(- % (apply + %&))

Function literals cannot be nested. So, while this is perfectly legal:

Aside from the fact that the bodies of function literals are
intended to be terse, simple expressions, making the prospect of
nested function literals a readability and comprehension nightmare,
there’s simply no way to disambiguate which function’s first argument
% is referring to.

Conditionals: if

ifis Clojure’s sole primitive conditional operator. Its
syntax is simple: if the value of the first expression in an if form is logically
true, then the result of the if form
is the value of the second expression. Otherwise, the result of the
if form is the value of the third
expression, if provided. The second and third expressions are only
evaluated as necessary.

Clojure conditionals determine logical truth to be anything other
than nil or false:

Note that if a conditional expression is logically false, and no
else expression is provided, the result of an
if expression is nil.[32]

Many refinements are built on top of if, including:

when, best used when
nil should be returned (or no
action should be taken) if a condition is false.

cond—similar to the else
if construction in Java and Ruby, and elif in Python—allows you to concisely
provide multiple conditions to check, along with multiple
then expressions if a given conditional is
true.

if-let and when-let, which are compositions of let with if and when, respectively: if the value of the
test expression is logically true, it is bound to a local for the
extent of the then expression.

Warning

Clojure provides true? and false? predicates, but these are unrelated to if conditionals. For example:

(true? "string")
;= false
(if "string" \t \f)
;= \t

true? and false? check for the Boolean values true and false, not the logical truth condition used
by if, which is equivalent to
(or (not (nil? x)) (true? x)) for
any value x.

Looping: loop and recur

Clojure provides a number of useful imperative looping
constructs, including doseq and
dotimes, all of which are built upon
recur. recur transfers control to the local-most
loop head without consuming stack space, which is
defined either by loop or a function.
Let’s take a look at a very simple countdown loop:

(loop [x 5]
(if (neg? x)
x
(recur (dec x))))
;= -1

loop establishes bindings
via an implicit let form, so it
takes a vector of binding names and initial values.

If the final expression within a loop form consists of a value, that is
taken as the value of the form itself. Here, when x is negative, the loop form returns the value of x.

A recur form will transfer
control to the local-most loop head, in this case the loop form, resetting the local bindings to
the values provided as arguments to recur. In this case, control jumps to the
beginning of the loop form, with
x bound to the value (dec x).

Loop heads are also established by functions, in which case
recur rebinds the function’s
parameters using the values provided as arguments to recur:

Appropriate use of recur. recur is a very low-level
looping and recursion operation that is usually not necessary:

When they can do the job, use the higher-level looping and
iteration forms found in Clojure’s core library, doseq and dotimes.

When “iterating” over a collection or sequence, functional
operations like map, reduce, for, and so on are almost always
preferable.

Because recur does not consume
stack space (thereby avoiding stack overflow errors), recuris critical when
implementing certain recursive algorithms. In addition, because it
allows you to work with numerics without the overhead of boxed
representations, recur is very useful
in the implementation of many mathematical and data-oriented operations.
See Visualizing the Mandelbrot Set in Clojure for a live example of recur within such circumstances.

Finally, there are scenarios where the accumulation or consumption
of a collection or set of collections is complicated enough that
orchestrating things with a series of purely functional operations using
map, reduce, and so on is either difficult or
inefficient. In these cases, the use of recur (and sometimes loop in order to set up intermediate loop
heads) can provide an important escape hatch.

Referring to Vars: var

Symbols that name a var evaluate to that var’s
value:

(def x 5)
;= #'user/x
x
;= 5

However, there are occasions when you’d like to have a reference
to the var itself, rather than the value it holds. The var special form does this:

(var x)
;= #'user/x

You’ve seen a number of times now how vars are printed in the
REPL: #', followed by a symbol. This
is reader syntax that expands to a call to var:

Java Interop: . and new

All Java interoperability—instantiation, static and
instance method invocation, and field access—flows through the new and .
special forms. That said, the Clojure reader provides some syntactic
sugar on top of these primitive interop forms that makes Java interop
more concise in general and more syntactically consistent with Clojure’s
notion of function position for method calls and instantiation. Thus,
it’s rare to see . and new used directly, but you will nevertheless
come across them out in the wild at some point:

The sugared syntax shown in Table 1-3 is idiomatic and should be preferred
in every case over direct usage of the . and new
special forms. Java interop is discussed in depth in Chapter 9.

Exception Handling: try and throw

These special forms allow you to participate in and use
the exception-handling and -throwing mechanisms in Java from Clojure.
They are explained in Exceptions and Error Handling.

Specialized Mutation: set!

While Clojure emphasizes the use of immutable data structures and
values, there are contexts where you need to effect an in-place mutation
of state. The most common settings for this involve the use of setter
and other stateful methods on Java objects you are using in an interop
setting; for the remaining cases, Clojure provides set!, which can be used to:

Set the thread-local value of vars that have a non-root
binding, discussed in Dynamic Scope

Set the value of mutable fields defined by deftype; see Types for details of that usage

Primitive Locking: monitor-enter and monitor-exit

These are lock primitives that allow Clojure to
synchronize on the monitor associated with every Java object. You should
never need to use these special forms, as there’s a macro, locking, that ensures proper acquisition and
release of an object’s monitor. See Locking for details.

[18] Special forms are always given precedence when resolving
symbols in function position. For example, you can have a var or
local named def, but you will
not be able to refer to the value of that var or local in function
position—though you can refer to that value anywhere else.

[19] Paul Graham’s The Roots of Lisp (http://www.paulgraham.com/rootsoflisp.html) is a brief
yet approachable precis of the fundamental operations of computation,
as originally discovered and enumerated by John McCarthy. Though that
characterization of computation was made more than 50 years ago, you
can see it thriving in Clojure today.

[20] If you were to open the core.clj file from
Clojure’s source repository, you will see this bootstrapping in
action: everything from when and
or to defn and = is defined in Clojure itself. Indeed, if
you were so motivated, you could implement Clojure (or another
language of your choosing) from scratch, on your own, on top of
Clojure’s special forms.

[21] This sort of syntactic extension generally requires
macros, which are treated in detail in Chapter 5.

[22] The other alternative would be for let (and all other forms that utilize
do) to (re?) implement its own
semantics of “do several things and return the value of the last
expression”: hardly a reasonable thing to do.

[23] See Namespaces for a discussion of
the typical usage of vars as stable references to values in
namespaces; see Vars for more a more
comprehensive treatment of them, including esoteric usages related
to dynamic scope and thread-local references.

[24] Thus the term: destructuring is undoing
(de-) the creation of the data
structure.

[25] Values in the source collection that have no corresponding
bound name are simply not bound within the context of the let form; you do not need to fully match
the structure of the source collection, but sequential
destructuring forms do need to be “anchored” at the beginning of
the source.

[26] Again, note the use of underscores (_) in this destructuring form to
indicate an ignored binding, similar to the idiom discussed in the
note earlier in this chapter.

[28] This is due to the polymorphic behavior of get, which looks up values in a
collection given a key into that collection; in the case of these
indexable sequential values, get uses indices as keys. For more about
get, see Associative.

[29] Python is a language that supports this usage pervasively,
where every argument may be named and provided in any order in a
function call, and argument defaults can be provided when a
function is defined.

[30] Since the name of the arguments to the function is
irrelevant, the function literal generates a unique symbol for
each argument to refer to them; in this case, p1__285# and p2__286#.