C-style ad hoc debauchery.

Download from Wow! eBook <www.wowebook.com>

26

CHAPTER 2 Drinking from the Clojure firehose

2.3.2

Defining functions

An anonymous (unnamed) Clojure function can be defined as a special form. A spe-

cial form is a Clojure expression that’s part of the core language, but not created in

terms of functions, types, or macros.

An example of a function taking two elements that returns a set of those elements

would be defined as

(fn mk-set [x y] #{x y})

;=> #<user$eval__1$mk_set__2 user$eval__1$mk_set__2@d3576a2>

Entering this function definition in a Clojure REPL gives us a seemingly strange result.

This is because the REPL is showing its internal name for the function object returned

by the fn special form. This is far from satisfying, given that now that the function has

been defined, there’s no apparent way to execute it. It should be noted that the mk-set

symbol is optional and doesn’t correspond to a globally accessible name for the func-

tion, but instead to a name internal to the function itself used for self-calls. Recall from

the previous section that the function call form is always (some-function arguments):

((fn [x y] #{x y}) 1 2)

;=> #{1 2}

The second form to define functions allows for arity overloading of the invocations of

a function. Arity refers to the differences in the argument count that a function will

accept. Changing our previous simple set-creating function to accept either one or

two arguments would be represented as

(fn

([x] #{x})

([x y] #{x y}))

The difference from the previous form is that we can now have any number of argu-

ment/body pairs as long as the arity of the arguments differ. Naturally, the execution

of such a function for one argument would be

((fn

([x] #{x})

([x y] #{x y})) 42)

;=> #{42}

As you saw, arguments to functions are bound one-for-one to symbols during the func-

tion call, but there is a way for functions to accept a variable5 number of arguments:

((fn arity2 [x y] [x y]) 1 2 3)

;=> java.lang.IllegalArgumentException: Wrong number of args passed

Clearly, calling the arity2 function with three arguments won’t work. But what if we

wanted it to take any number of arguments? The way to denote variable arguments is

to use the & symbol followed by a symbol. Every symbol in the arguments list before

5 The implementation details of Clojure prevent the creation of functions with an arity larger than 20, but in

practice this should rarely, if ever, be an issue.

Download from Wow! eBook <www.wowebook.com>

Making things happen: functions

27

the & will still be bound one-for-one to the same number of arguments passed during

the function call. But any additional arguments will be aggregated in a sequence

bound to the symbol following the & symbol:

((fn arity2+ [x y & z] [x y z]) 1 2)

;=> [1 2 nil]

((fn arity2+ [x y & z] [x y z]) 1 2 3 4)

;=> [1 2 (3 4)]

((fn arity2+ [x y & z] [x y z]) 1)

;=> java.lang.IllegalArgumentException: Wrong number of args passed

Of course, arity2+ still requires at least two arguments. But this isn’t satisfactory, as it

quickly becomes clear that to write programs using only this form would be cumber-

some, repetitive, and overly verbose. Thankfully, Clojure provides another, more con-

venient form to create named functions.

2.3.3

Simplifying function definitions with def and defn

The def special form is a way to assign a symbolic name to a piece of Clojure data. Clo-

jure functions are first-class; they’re equal citizens with data, allowing assignment to

Vars, storage in collections, and as arguments to (or returned from) other functions.

This is different from programming languages where functions are functions and data

are data, and there’s a world of capability available to the latter that’s incongruous to

the former.

Therefore, in order to associate a name with our previous function using def,

we’d use

(def make-a-set

(fn

([x] #{x})

([x y] #{x y})))

And we could now call it in a more intuitive way:

(make-a-set 1)

;=> #{1}

(make-a-set 1 2)

;=> #{1 2}

There’s another way to define functions in Clojure using the defn macro. While cer-

tainly a much nicer way to define and consequently refer to functions by name, using

def as shown is still cumbersome to use. Instead, the simplest defn syntax is a conve-

nient and concise way to create named functions that looks similar to the original fn

form, and allow an additional documentation string:

(defn make-a-set

"Takes either one or two values and makes a set from them"

([x] #{x})

([x y] #{x y}))

The function can again be called the same as we saw before.

Download from Wow! eBook <www.wowebook.com>

28

CHAPTER 2 Drinking from the Clojure firehose

2.3.4

In-place functions with #()

Clojure provides a shorthand notation for creating an anonymous function using the

#() reader feature. In a nutshell, reader features are analogous to preprocessor direc-

tives in that they signify that some given form should be replaced with another at read

time. In the case of the #() form, it’s effectively replaced with the special form fn. In

fact, anywhere that it’s appropriate to use #(), it’s likewise appropriate for the fn spe-

cial form.

The #() form can also accept arguments that are implicitly declared through the

use of special symbols prefixed with %:

(def make-a-list_ #(list %))

(def make-a-list1 #(list %1))

(def make-a-list2 #(list %1 %2))

(def make-a-list3 #(list %1 %2 %3))

(def make-a-list3+ #(list %1 %2 %3 %&))

(make-a-list_ 1)

;=> (1)

(make-a-list3+ 1 2 3 4 5)

;=> (1 2 3 (4 5))

The %& argument in make-a-list3+ is used to specify the variable arguments as dis-

cussed previously.

2.4

Vars

Programmers are typically accustomed to dealing with variables and mutation. Clo-

jure’s closest analogy to the variable is the Var. A Var is named by a symbol and holds

a single value. Its value can be changed while the program is running, but this is best

reserved for the programmer making manual changes. A Var’s value can also be

shadowed by a thread local value, though this doesn’t change its original value or

root binding.

2.4.1

Declaring bindings using def

Using def is the most common way to create Vars in Clojure:

(def x 42)

Using def to associate the value 42 to the symbol x creates what’s known as a root

binding —a binding that’s the same across all threads, unless otherwise rebound rela-

tive to specific threads. By default, all threads start with the root binding, which is

their associated value in the absence of a thread-bound value.

The trivial case is that the symbol x is bound to the value 42. Because we used def

to create the Var’s root binding, we should observe that even other threads will view

the same root binding by default:

(.start (Thread. #(println "Answer: " x)))

; Answer: 42

Download from Wow! eBook <www.wowebook.com>

Locals, loops, and blocks

29

Vars don’t require a value; instead we can simply declare them and defer the responsi-

bility of binding their values to individual threads:6

(def y)

y

;=> java.lang.IllegalStateException: Var user/y is unbound.

Functions and vars theoretically provide all you need to implement any algorithm,

and some languages leave you with exactly these “atomic” constructs.

2.5

Locals, loops, and blocks

Clojure’s function and value binding capabilities provide a basis for much of what a

developer needs to start getting operational code, but a large part of the story is miss-

ing. Clojure also provides capabilities for creating local value bindings, looping con-

structs, and aggregating blocks of functionality.

2.5.1

Blocks

Use the do form when you have a series or block of expressions that need to be treated

as one. All the expressions will be evaluated, but only the last one will be returned:

(do

6

(+ 5 4)

3)

;=> 3

The expressions 6 and (+ 5 4) are perfectly valid and legal. The addition in (+ 5 4)

is even done, but the value is thrown away—only the final expression 3 is returned.

The middle bits of the do form are typically where the side-effects occur.

2.5.2

Locals

Clojure doesn’t have local variables, but it does have locals; they just can’t vary. Locals

are created and their scope defined using a let form, which starts with a vector that

defines the bindings, followed by any number of expressions that make up the body.

The vector starts with a binding form (usually just a symbol), which is the name of a

new local. This is followed by an expression whose value will be bound to this new

local for the remainder of the let form. You can continue pairing binding names and

expressions to create as many locals as you need. All of them will be available in the

body of the let:

(let [r 5

pi 3.1415

r-squared (* r r)]

(println "radius is" r)

(* pi r-squared))

6 We’ll talk more about per-thread bindings in chapter 11.

Download from Wow! eBook <www.wowebook.com>

30

CHAPTER 2 Drinking from the Clojure firehose

The body is sometimes described as an “implicit do” because it follows the same rules:

you may include any number of expressions and all will be evaluated, but only the

value of the last one is returned.

All of the binding forms in the previous example are simple symbols: r, pi, and r-

squared. More complex binding expressions can be used to pull apart expressions

that return collections. This feature is called destructuring: see section 2.9 for details.

Because they’re immutable, locals can’t be used to accumulate results; instead,

you’d use a high level function or loop/recur form.

2.5.3

Loops

The classic way to build a loop in a Lisp is a recursive call, and it’s in Clojure as well.

Using recursion sometimes requires thinking about your problem in a different way

than imperative languages encourage; but recursion from a tail position is in many

ways like a structured goto, and has more in common with an imperative loop than it

does with other kinds of recursion.

RECUR

Clojure has a special form called recur that’s specifically for tail recursion:

(defn print-down-from [x]

(when (pos? x)

(println x)

(recur (dec x))))

This is nearly identical to how you’d structure a while loop in an imperative language.

One significant difference is that the value of x isn’t decremented somewhere in the

body of the loop. Instead, a new value is calculated as a parameter to recur, which

immediately does two things: rebinds x to the new value and returns control to the top

of print-down-from.

If the function has multiple arguments, the recur call must as well, just as if you

were calling the function by name instead of using the recur special form. And just as

with a function call, the expressions in the recur are evaluated in order first and only

then bound to the function arguments simultaneously.

The previous example doesn’t concern itself with return values; it’s just about the

println side effects. Here’s a similar loop that builds up an accumulator and returns

the final result:

(defn sum-down-from [sum x]

(if (pos? x)

(recur (+ sum x) (dec x))

sum))

The only ways out of the function are recur, which isn’t really a way out, and sum. So

when x is no longer positive, the function will return the value of sum:

(sum-down-from 0 10)

;=> 55

Download from Wow! eBook <www.wowebook.com>

Locals, loops, and blocks

31

You may have noticed that the two preceding functions used different blocks: the first

when and the second if. You’ll often see one or the other used as a conditional, but

it’s not always immediately apparent why. In general, the reasons to use when are

 No else-part is associated with the result of a conditional.

 You require an implicit do in order to perform side-effects.

The reasons for the use of if would therefore be the inverse of those listed.

LOOP

Sometimes you want to loop back not to the top of the function, but to somewhere

inside. For example, in sum-down-from you might prefer that callers not have to pro-

vide an initial value for sum. To help, there’s a loop form that acts exactly like let but

provides a target for recur to jump to. It’s used like this:

(defn sum-down-from [initial-x]

(loop [sum 0, x initial-x]

(if (pos? x)

(recur (+ sum x) (dec x))

sum)))

Upon entering the loop form, the locals sum and x are initialized, just as they would

be for a let.

A recur always loops back to the closest enclosing loop or fn, so in this case it’ll go

to the loop. The loop locals are rebound to the values given in recur. The looping

and rebinding will continue until finally x is no longer positive. The return value of

the whole loop expression is sum, just as it was for the earlier function.

TAIL POSITION

Now that we’ve looked at a couple examples of how to use recur, we must discuss an

important restriction. The recur form can only appear in the tail position of a func-

tion or loop. So what’s a tail position? Succinctly, a form is in the tail position of an

expression when its value may be the return value of the whole expression. Consider

this function:

(defn absolute-value [x]

(if (pos? x)

x ; "then" clause

(- x))) ; "else" clause

It takes a single parameter and names it x. If x is already a positive number, then x is

returned; otherwise the opposite of x is returned.

The if form is in the function’s tail position because whatever it returns, the whole

function will return. The x in the “then” clause is also in a tail position of the function.

But the x in the “else” clause is not in the function’s tail position because the value of x

is passed to the - function, not returned directly. The else clause as a whole (- x) is in

a tail position.

If you try to use the recur form somewhere other than a tail position, Clojure will

remind you at compile time:

Download from Wow! eBook <www.wowebook.com>

32

CHAPTER 2 Drinking from the Clojure firehose

(fn [x] (recur x) (println x))

; java.lang.UnsupportedOperationException:

; Can only recur from tail position

You’ve seen how Clojure provides core functionality available to most popular pro-

gramming languages, albeit from a different bent. But in the next section, we’ll cover

the notion of quoting forms, which are in many ways unique to the Lisp family of lan-

guages and may seem alien to programmers coming from classically imperative and/

or object-oriented languages.

2.6

Preventing things from happening: quoting

Clojure has two quoting forms: quote and syntax-quote. Both are simple bits of syntax

you can put in front of a form in your program. They’re the primary ways for includ-

ing literal scalars and composites in your Clojure program without evaluating them as

code. But before quoting forms can make sense, you need a solid understanding of

how expressions are evaluated.

2.6.1

Evaluation

When a collection is evaluated, each of its contained items is evaluated first:7

(cons 1 [2 3])

If you enter this at the REPL, the form as a whole will be evaluated. In this specific

example, the function cons “constructs” a new sequence with its first argument in the

front of the sequence provided as its second. Because the form is a list, each of the

items will be evaluated first. A symbol, when evaluated, is resolved to a local, a Var, or a

Java class name. If a local or a Var, its value will be returned:

cons

;=> #<core$cons__3806 clojure.core$cons__3806@24442c76>

Literal scalar values evaluate to themselves—evaluating one just returns the same

thing:

1

;=> 1

The evaluation of another kind of collection, a vector, starts again by evaluating the

items it contains. Because they’re literal scalars, nothing much happens. Once that’s

done, evaluation of the vector can proceed. Vectors, like scalars and maps, evaluate to

themselves:

[2 3]

;=> [2 3]

Now that all the items of the original list have been evaluated (to a function, the

number 1, and the vector [2 3]), evaluation of the whole list can proceed. Lists are

7 ...unless it’s a list that starts with the name of a macro or special form. We’ll get to that later.

Download from Wow! eBook <www.wowebook.com>

Preventing things from happening: quoting

33

evaluated differently from vectors and maps: they call functions, or trigger special

forms, as shown:

(cons 1 [2 3])

;=> (1 2 3)

Whatever function was at the head of the list, cons in this case, is called with the

remaining items of the list as arguments.

2.6.2

Quoting

Using a special form looks like calling a function—a symbol as the first item of a list:

(quote tena)

Each special form has its own evaluation rules. The quote special form simply pre-

vents its argument from being evaluated at all. Though the symbol tena by itself might

evaluate to the value of a Var with the value 9, when it’s inside a quote form, it won’t:

(def tena 9)

(quote tena)

;=> tena

Instead, the whole form evaluates to just the symbol itself. This works for arbitrarily

complex arguments to quote: nested vectors, maps, even lists that would otherwise be

function calls, macro calls, or even more special forms. The whole thing is returned:

(quote (cons 1 [2 3]))

;=> (cons 1 [2 3])

There are a few reasons you might use the quote form, but by far the most common is

so that you can use a literal list as a data collection without having Clojure try to call a

function. We’ve been careful to use vectors in the examples so far in this section

because vectors are never themselves function calls. But if we wanted to use a list

instead, a naive attempt would fail:

(cons 1 (2 3))

; java.lang.ClassCastException:

; java.lang.Integer cannot be cast to clojure.lang.IFn

That’s Clojure telling us that an integer (the number 2 here) can’t be used as a func-

tion. So we have to prevent the form (2 3) from being treated like a function call—

exactly what quote is for:

(cons 1 (quote (2 3)))

;=> (1 2 3)

In other Lisps, this need is so common that they provide a shortcut: a single quote.

Although it’s used less in Clojure, it’s still provided. The previous example can also be

written as

(cons 1 '(2 3))

;=> (1 2 3)

Download from Wow! eBook <www.wowebook.com>

34

CHAPTER 2 Drinking from the Clojure firehose

And look at that: one less pair of parens—always welcome in a Lisp. Remember

though that quote affects all of its argument, not just the top level. So even though it

worked in the preceding examples to replace [] with '(), this may not always give you

the results you want:

[1 (+ 2 3)] ;=> [1 5]

'(1 (+ 2 3)) ;=> (1 (+ 2 3))

Finally, note that the empty list () already evaluates to itself; it doesn’t need to be

quoted. Quoting the empty list isn’t idiomatic Clojure.

SYNTAX-QUOTE

Like the quote, syntax-quote prevents its argument and subforms from being evalu-

ated. Unlike quote, it has a few extra features that make it ideal for constructing col-

lections to be used as code.

Syntax-quote is written as a single back-quote:

`(1 2 3)

;=> (1 2 3)

It doesn’t expand to a simple form like quote, but to whatever set of expressions is

required to support the following features.8

SYMBOL AUTO-QUALIFICATION

A symbol can begin with a namespace and a slash. These can be called qualified symbols:

clojure.core/map

clojure.set/union

i.just.made.this.up/quux

Syntax-quote will automatically qualify all unqualified symbols in its argument:

`map

;=> clojure.core/map

Ìnteger

;=> java.lang.Integer

`(map even? [1 2 3])

;=> (clojure.core/map clojure.core/even? [1 2 3])

If the symbol doesn’t name a Var or class that exists yet, syntax-quote will use the cur-

rent namespace:

ìs-always-right

;=> user/is-always-right

This behavior will come in handy in chapter 8, when we discuss macros.

2.6.3

Unquote

As you discovered, the quote special form prevents its argument, and all of its sub-

forms, from being evaluated. But there will come a time when you’ll want some of its

8 A future version of Clojure is likely to expand the back-quote to syntax-quote at read time and implement the

rest of syntax-quote’s features as a macro or special form.

Download from Wow! eBook <www.wowebook.com>

Preventing things from happening: quoting

35

constituent forms to be evaluated. The way to accomplish this feat is to use what’s

known as an unquote. An unquote is used to demarcate specific forms as requiring

evaluation by prefixing them with the symbol ~ within the body of a syntax-quote:

`(+ 10 (* 3 2))

;=> (clojure.core/+ 10 (clojure.core/* 3 2))

`(+ 10 ~(* 3 2))

;=> (clojure.core/+ 10 6)

What just happened? The final form uses an unquote to evaluate the subform (* 3

2), which of course performs a multiplication of 3 and 2, thus inserting the result into

the outermost syntax-quoted form. The unquote can be used to denote any Clojure

expression as requiring evaluation:

`(1 2 ~3)

;=> (1 2 3)

(let [x 2]

`(1 ~x 3))

;=> (1 2 3)

`(1 ~(2 3))

;=> java.lang.ClassCastException: java.lang.Integer

Whoops! By using the unquote, we’ve told Clojure that the marked form should be

evaluated. But the marked form here is (2 3), and what happens when Clojure

encounters an expression like this? It attempts to evaluate it as a function! Therefore,

care needs to be taken with unquote to ensure that the form requiring evaluation is of

the form that you expect. The more appropriate way to perform the previous task

would thus be

(let [x '(2 3)] `(1 ~x))

;=> (1 (2 3))

This provides a level of indirection such that the expression being evaluated is no lon-

ger (2 3) but x. But this new way breaks the pattern of the previous examples that

returned a list of (1 2 3).

2.6.4

Unquote-splicing

Clojure provides a handy feature to solve exactly the problem posed earlier. A variant

of unquote called unquote-splicing works similarly to unquote, but a little differently:

(let [x '(2 3)] `(1 ~@x))

;=> (1 2 3)

Note the @ in ~@, which tells Clojure to unpack the sequence x, splicing it into the

resulting list rather than inserting it as a nested list.

Download from Wow! eBook <www.wowebook.com>

36

CHAPTER 2 Drinking from the Clojure firehose

2.6.5

Auto-gensym

Sometimes you need an unqualified symbol, such as for a parameter or let local

name. The easiest way to do this inside a syntax-quote is to append a # to the symbol

name. This will cause Clojure to generate a new unqualified symbol:

`potion#

;=> potion__211__auto__

Sometimes even this isn’t enough, either because you need to refer to the same sym-

bol in multiple syntax-quotes or because you want to capture a particular unqualified

symbol.

Until this point, we’ve covered many of the basic features making Clojure a unique

flavor of Lisp. But one of the main goals that Clojure excels at meeting is that of

interoperability with a host language and runtime, namely Java and the Java Virtual

Machine.

2.7

Leveraging Java via interop

Clojure is symbiotic with its host,9 providing its rich and powerful features, while Java

provides an object model, libraries, and runtime support. In this section, we’ll take a

brief look at how Clojure allows you to access Java classes and class members, and how

you can create instances and access their members.

2.7.1

Accessing static class members

Clojure provides powerful mechanisms for accessing, creating, and mutating Java

classes and instances. The trivial case is accessing static class properties:

java.util.Locale/JAPAN

;=> #<Locale ja_JP>

Idiomatic Clojure prefers that you access static class members using a syntax like

accessing a namespace-qualified Var:

(Math/sqrt 9)

;=> 3.0

The preceding call is to the java.lang.Math#sqrt static method.

2.7.2

Creating Java class instances

Creating Java class instances is likewise a trivial matter with Clojure. The new special

form closely mirrors the Java model:

(new java.util.HashMap {"foo" 42 "bar" 9 "baz" "quux"})

;=> #<HashMap {baz=quux, foo=42, bar=9}>

The second, more succinct, Clojure form to create instances is actually the idiomatic

form:

9 We’ll focus on the Java Virtual Machine throughout this book, but Clojure has also been hosted on the .NET

Common Language Runtime (CLR) and JavaScript (http://clojurescript.n01se.net/repl/).

Download from Wow! eBook <www.wowebook.com>

Leveraging Java via interop

37

(java.util.HashMap. {"foo" 42 "bar" 9 "baz" "quux"})

;=> #<HashMap {baz=quux, foo=42, bar=9}>

As you can see, the class name was followed by a dot in order to signify a constructor

call.

2.7.3

Accessing Java instance members with the . operator

To access instance properties, precede the property or method name with a dot:

(.x (java.awt.Point. 10 20))

;=> 10

This returns the value of the field x from the Point instance given.

To access instance methods, the dot form allows an additional argument to be

passed to the method:

(.divide (java.math.BigDecimal. "42") 2M)

;=> 21M

The preceding example calls the #divide method on the class BigDecimal.

2.7.4

Setting Java instance properties

In the absence of mutators in the form setXXX, Java instance properties can be set via

the set! function:

(let [origin (java.awt.Point. 0 0)]

(set! (.x origin) 15)

(str origin))

;=> "java.awt.Point[x=15,y=0]"

The first argument to set! is the instance member access form.

2.7.5

The .. macro

When working with Java, it’s common practice to chain together a sequence of

method calls on the return type of the previous method call:

new java.util.Date().toString().endsWith("2010") /* Java code */

Using Clojure’s dot special form, the following code is equivalent:

(.endsWith (.toString (java.util.Date.)) "2010") ; Clojure code

;=> true

Though correct, the preceding code is difficult to read and will only become more so

when we lengthen the chain of method calls. To combat this, Clojure provides the ..

macro, which can simplify the call chain as follows:

(.. (java.util.Date.) toString (endsWith "2010"))

The preceding .. call closely follows the equivalent Java code and is much easier to

read. Bear in mind, you might not see .. used often in Clojure code found in the wild

outside of the context of macro definitions. Instead, Clojure provides the -> and ->>

macros, which can be used similarly to the .. macro but are also useful in non-interop

Download from Wow! eBook <www.wowebook.com>

38

CHAPTER 2 Drinking from the Clojure firehose

situations, thus making them the preferred method call facilities in most cases. The ->

and ->> macros are covered in more depth in the introduction to chapter 8.

2.7.6

The doto macro

When working with Java, it’s also common to initialize a fresh instance by calling a set

of mutators:

java.util.HashMap props = new java.util.HashMap(); /* More java code. */

props.put("HOME", "/home/me"); /* Sorry. */

props.put("SRC", "src");

props.put("BIN", "classes");

But using this method is overly verbose and can be streamlined using the doto macro,

which takes the form

(doto (java.util.HashMap.)

(.put "HOME" "/home/me")

(.put "SRC" "src")

(.put "BIN" "classes"))

;=> #<HashMap {HOME=/home/me, BIN=classes, SRC=src}>

Though these Java and Clojure comparisons are useful, it shouldn’t be assumed that

their compiled structures are the same.

2.7.7

Defining classes

Clojure provides the reify and deftype macros as possible ways to create realizations

of Java interfaces, but we’ll defer covering them until chapter 9. Additionally, Clojure

provides a macro named proxy that can be used to implement interfaces and extend

base classes on the fly. Similarly, using the gen-class macro, you can generate statically

named classes. More details about proxy and gen-class are available in chapter 10.

2.8

Exceptional circumstances

We’ll now talk briefly about Clojure’s facilities for handling exceptions. Like Java, Clo-

jure provides a couple of forms for throwing and catching runtime exceptions:

namely throw and catch, respectively.

2.8.1

A little pitch and catch

The mechanism to throw an exception is fairly straightforward:

(throw (Exception. "I done throwed"))

;=> java.lang.Exception: I done throwed

The syntax for catching exceptions in Clojure is similar to that of Java:

(defn throw-catch [f]

[(try

(f)

(catch ArithmeticException e "No dividing by zero!")

(catch Exception e (str "You are so bad " (.getMessage e)))

Download from Wow! eBook <www.wowebook.com>

Namespaces

39

(finally (println "returning... ")))])

(throw-catch #(/ 10 5))

; returning...

;=> [2]

(throw-catch #(/ 10 0))

; returning...

;=> ["No dividing by zero!"]

(throw-catch #(throw (Exception. "foo")))

; returning...

;=> ["You are so bad foo"]

The major difference between the way that Java handles exceptions compared to Clo-

jure is that Clojure doesn’t adhere to checked exception requirements. In the next,

final section of our introduction to Clojure, we present namespaces, which might look

vaguely familiar if you’re familiar with Java or Common Lisp.

2.9

Namespaces

Clojure’s namespaces provide a way to bundle related functions, macros, and values.

In this section, we’ll briefly talk about how to create namespaces and how to reference

and use things from other namespaces.

2.9.1

Creating namespaces using ns

To create a new namespace, you can use the ns macro:

(ns joy.ch2)

Whereupon your REPL prompt will now display as:

joy.ch2=>

This prompt shows that you’re working within the context of the joy.ch2 namespace.

Clojure also provides a Var *ns* that holds the value of the current namespace. Any

Var created will be a member of the current namespace:

(defn hello [] (println "Hello Cleveland!"))

(defn report-ns [] (str "The current namespace is " *ns*))

(report-ns)

;=> "The current namespace is joy.ch2"

Entering a symbol within a namespace will cause Clojure to attempt to look up its

value within the current namespace:

hello

;=> #<ch2$hello joy.ch2$hello@2af8f5>

You can create new namespaces at any time:

(ns joy.another)

Again, you’ll notice that your prompt has changed, indicating that the new context is

joy.another. Attempting to run report-ns will no longer work:

Download from Wow! eBook <www.wowebook.com>

40

CHAPTER 2 Drinking from the Clojure firehose

(report-ns)

; java.lang.Exception:

; Unable to resolve symbol: report-ns in this context

This is because report-ns exists in the joy.ch1 namespace and is only accessible via

its fully qualified name joy.ch2/report-ns. But this will only work for namespaces

created locally or those previously loaded, which we’ll discuss next.

2.9.2

Loading other namespaces with :require

Creating a namespace is straightforward, but how do you load namespaces? Clojure

provides a convenience directive :require to take care of this task. Observe the

following:

(ns joy.req

(:require clojure.set))

(clojure.set/intersection #{1 2 3} #{3 4 5})

;=> #{3}

Using :require indicates that you want the clojure.set namespace loaded, but you

don’t want the mappings of symbols to functions in the joy.req namespace. You can

also use the :as directive to create an additional alias to clojure.set:

(ns joy.req-alias

(:require [clojure.set :as s]))

(s/intersection #{1 2 3} #{3 4 5})

;=> #{3}

The qualified namespace form looks the same as a call to a static class method. The

difference is that a namespace symbol can only be used as a qualifier, whereas a class

symbol can also be referenced independently:

clojure.set

; java.lang.ClassNotFoundException: clojure.set

java.lang.Object

;=> java.lang.Object

The vagaries of namespace mappings from symbols to Vars both qualified and unqual-

ified have the potential for confusion between class names and static methods in the

beginning, but the differences will begin to feel natural as you progress. In addition,

idiomatic Clojure code will tend to use my.Class and my.ns for naming classes and

namespaces respectively, to help eliminate potential confusion.

2.9.3

Loading and creating mappings with :use

Sometimes you’ll want to create mappings from Vars in another namespace to names

in your own, in order to avoid calling each function or macro with the qualifying

namespace symbol. To create these unqualified mappings, Clojure provides the :use

directive:

(ns joy.use-ex

(:use [clojure.string :only [capitalize]]))

Download from Wow! eBook <www.wowebook.com>

Namespaces

41

(map capitalize ["kilgore" "trout"])

;=> ("Kilgore" "Trout")

The :use directive indicates that only the function capitalize should be mapped in

the namespace joy.use-ex. Specifying the Vars that you’d like explicit mappings for

is good practice in Clojure, as it avoids creating many unnecessary names within a

namespace. Unnecessary names increase the odds of names clashes, which you’ll see

next. A similar directive to :use for managing precise mappings is :exclude

(ns joy.exclusion

(:use [clojure.string :exclude [capitalize]]))

; WARNING: replace already refers to: #'clojure.core/replace in namespace:

; joy.exclusion, being replaced by: #'clojure.string/replace

; WARNING: reverse already refers to: #'clojure.core/reverse in namespace:

; joy.exclusion, being replaced by: #'clojure.string/reverse

(map capitalize ["kilgore" "trout"])

; java.lang.Exception: Unable to resolve symbol: capitalize in this context

The :exclude directive indicates that we wanted to map names for all of clojure.

string’s Vars except for capitalize. Indeed, any attempt to use capitalize directly

throws an exception. But it’s still accessible via clojure.string/capitalize. The rea-

son for this accessibility is because :use implicitly performs a :require directive in

addition to creating mappings. As you might’ve noticed, the creation of the joy.

exclusion namespace signaled two warnings. The reason was that the clojure.

string namespace defines two functions reverse and replace that are already

defined in the clojure.core namespace—which was already loaded by using ns.

Therefore, when either of those functions are used, the last Var definition wins:

(reverse "abc")

;=> "cba"

(clojure.core/reverse "abc")

(\c \b \a)

The clojure.string version of reverse takes precedence over the clojure.core ver-

sion, which may or may not be what we wanted. You should always strive to eliminate

the warnings that Clojure presents in these cases. The most obvious strategy for resolv-

ing these particular warnings would be to use the :require directive to create a

namespace alias with :as as we showed in the previous section.

2.9.4

Creating mappings with :refer

Clojure also provides a :refer directive that works almost exactly like :use except

that it only creates mappings for libraries that have already been loaded:

(ns joy.yet-another

(:refer joy.ch1))

(report-ns)

;=> "The current namespace is #<Namespace joy.yet-another>"

Download from Wow! eBook <www.wowebook.com>

42

CHAPTER 2 Drinking from the Clojure firehose

The use of :refer in this way creates a mapping from the name report-ns to the

actual function located in the namespace joy.ch2 so that the function can be called

normally. You could also set an alias for the same function using the :rename keyword

taking a map, as shown:

(ns joy.yet-another

(:refer joy.ch1 :rename {hello hi}))

(hi)

; Hello Cleveland!

Any namespaces referenced must already be loaded implicitly by being previously

defined or by being one of Clojure’s core namespaces, or explicitly loaded through the

use of :require. It should be noted that :rename also works with the :use directive.

2.9.5

Loading Java classes with :import

To use unqualified Java classes within any given namespace, they should be imported

via the :import directive, as shown:

(ns joy.java

(:import [java.util HashMap]

[java.util.concurrent.atomic AtomicLong]))

(HashMap. {"happy?" true})

;=> #<HashMap {happy?=true}>

(AtomicLong. 42)

;=> 42

As a reminder, any classes in the Java java.lang package are automatically imported

when namespaces are created. We’ll discuss namespaces in more detail in sections 9.1

and 10.2.

2.10

Summary

We named this chapter “Drinking from the Clojure firehose”—and you’ve made it

through! How does it feel? We’ve only provided an overview of the topics needed to

move on to the following chapters instead of a full-featured language tutorial. Don’t

worry if you don’t fully grasp the entirety of Clojure the programming language;

understanding will come as you work your way through the book.

In the next chapter, we’ll take a step back and delve into some topics that can’t be

easily categorized, but that deserve attention because of their ubiquity. It’ll be short

and sweet and give you a chance to take a breath before moving into the deeper dis-

cussions on Clojure later in the book.

Download from Wow! eBook <www.wowebook.com>

Dipping our toes

in the pool

This chapter covers

 Truthiness

 Nil punning

 Destructuring

 Use the REPL to experiment

Deeper and broader topics will be covered in later chapters, but now’s a good time

to pick through an eclectic selection of smaller topics. The topics covered in this

chapter stand alone but are important. Covering them now will be a fun way to start

digging into practical matters of how to use Clojure.

We’ve covered a lot of conceptual ground in the previous chapter and built our

Clojure lexicon. In this chapter, we’ll take a bit of a detour into some fundamental

underpinnings driving idiomatic Clojure source code. First we’ll explore Clojure’s

straightforward notions of Truthiness,1 or the distinctions between values

1 As a deviation from the definition coined by Stephen Colbert in his television show The Colbert Report. Ours

isn’t about matters of gut feeling but rather about matters of Clojure’s logical truth ideal.

43

Download from Wow! eBook <www.wowebook.com>

44

CHAPTER 3 Dipping our toes in the pool

considered logical true and those considered logical false. Much of idiomatic Clojure

code is built with matters of Truthiness in mind, and we’ll discuss Clojure’s extremely

simple rules. After this we’ll then move on to the notion of nil punning, or treating an

empty sequence as nil. Those of you coming from a background in Lisp may recog-

nize the term, but Clojure handles nil punning differently. We’ll discuss the idioms

related to nil punning in Clojure and their rationale. We’ll then cover destructuring—

a powerful mechanism for pulling apart collection types and binding their constituent

parts as individual values. Using destructuring within your own code can often lead to

extremely concise and elegant solutions, and we’ll provide some examples to illustrate

this. Finally, we’ll sit down and pair-program together to gain an appreciation for the

power of Clojure’s Read-Eval-Print Loop (REPL).

3.1

Truthiness

Truthfulness may be an important virtue, but it doesn’t come up much in program-

ming. On the other hand, Truthiness, or the matter of logical truth values in Clojure, is

critical.

Clojure has one Boolean context: the test expression of the if form. Other forms

that expect Booleans—and, or, when, and so forth—are macros built on top of if. It’s

here that Truthiness matters.

3.1.1

What’s truth?

Every value looks like true to if, except for false and nil. That means that values

which some languages treat as false—zero-length strings, empty lists, the number zero,

and so on—are all treated as true in Clojure:

(if true :truthy :falsey) ;=> :truthy

(if [] :truthy :falsey) ;=> :truthy

(if nil :truthy :falsey) ;=> :falsey

(if false :truthy :falsey) ;=> :falsey

This may feel uncomfortable to you, depending on your background. But because

branches in a program’s logic are already one of the most likely places for complexity

and bugs, Clojure has opted for a simple rule. There’s no need to check a class’s defi-

nition to see if it acts like “false” when you think it should (as is sometimes required in

Python, for example). Every object is “true” all the time, unless it’s nil or false.

3.1.2

Don’t create Boolean objects

It’s possible to create an object that looks a lot like, but isn’t actually, false.

Java has left a landmine for you here, so take a moment to look at it so that you can

step past it gingerly and get on with your life:

(def evil-false (Boolean. "false")) ; NEVER do this

This creates a new instance of Boolean—and that’s already wrong! Because there are

only two possible values of Boolean, an instance of each has already been made for

Download from Wow! eBook <www.wowebook.com>

Nil pun with care

45

you—they’re named true and false.2 But here you’ve gone and done it anyway,

created a new instance of Boolean and stored it in a Var named evil-false. It looks

like false:

evil-false

;=> false

Sometimes it even acts like false:

(= false evil-false)

;=> true

But once it gains your trust, it’ll show you just how wicked it is by acting like true:

(if evil-false :truthy :falsey)

;=> :truthy

Java’s own documentation warns against the creation of this evil thing, and now you’ve

been warned again. If you just want to parse a string, use the Boolean class’s static

valueOf method instead of its constructor. This is the right way:

(if (Boolean/valueOf "false") :truthy :falsey)

;=> :falsey

3.1.3

nil versus false

Rarely do you need to differentiate between the two false values, but if you do, you can

use nil? and false?:

(when (nil? nil) "Actually nil, not false")

;=> "Actually nil, not false"

Keeping in mind the basic rule that everything in Clojure is truthy unless it’s false or

nil is an astonishingly powerful concept, allowing for elegant solutions. Often pro-

gramming languages have complicated semantics for Truthiness, but Clojure manages

to avoid those matters nicely. You’ll see this simplicity leveraged throughout this book

and in all examples of idiomatic Clojure source code.

Building on that theme, we’ll now discuss the matter of nil punning, which may or

may not surprise you given your background.

3.2

Nil pun with care

Because empty collections act like true in Boolean contexts, we need an idiom for

testing whether there’s anything in a collection to process. Thankfully, Clojure pro-

vides just such a technique:

(seq [1 2 3])

;=> (1 2 3)

(seq [])

;=> nil

2 Clojure’s true and false instances are the same as Java’s Boolean/TRUE and Boolean/FALSE, respectively.

Download from Wow! eBook <www.wowebook.com>

46

CHAPTER 3 Dipping our toes in the pool

The seq function returns a sequence view of a collection, or nil if the collection is

empty. In a language like Common Lisp, an empty list acts as a false value and can be

used as a pun (a term with the same behavior) for such in determining a looping ter-

mination. As you saw in section 2.3, Clojure’s empty sequences are instead truthy, and

therefore to use one as a pun for falsity will lead to heartache and despair. One solu-

tion that might come to mind is to use empty? in the test, leading to the awkward

phrase (when-not (empty? s) ...). Though it would work, this isn’t idiomatic. A

better solution would be to use seq as a termination condition, as in the following

function print-seq:

(defn print-seq [s]

(when (seq s)

(prn (first s))

(recur (rest s))))

(print-seq [1 2])

; 1

; 2

;=> nil

(print-seq [])

;=> nil

There are a number of points to take away from this example. First, the use of seq as a

terminating condition is the idiomatic way to test whether a sequence is empty. If we

tested just s instead of (seq s), then the terminating condition wouldn’t occur even

for empty collections, leading to an infinite loop.

PREFER DOSEQ An important point not mentioned is that it would be best to

use doseq in this case, but that wouldn’t allow us to illustrate our overarching

points: the Clojure forms named with do at the start (doseq, dotimes, do, and

so on) are intended for side-effects in their bodies and generally return nil as

their results.

Second, rest is used to consume the sequence on the recursive call, which can return

a sequence that’s either empty or not empty (has elements). Clojure also provides a

next function that returns a seq of the rest, or (seq (rest s)), and thus never returns

an empty sequence, but nil instead. But rest is appropriate here because we’re using

seq explicitly in each subsequent iteration. Finally, print-seq is a template for most

functions in Clojure, in that it shows that we should generally not assume seq has been

called on our collection arguments, but instead call seq within the function itself and

process based on its result. Using this approach fosters a more generic handling of col-

lections, a topic that we explore in great detail in chapter 5. In the meantime, it’s

important to keep in mind the difference between empty collections and false values;

otherwise your attempts at nil punning may cause groans all around.

To top off our trifecta of core Clojure concepts, we next explore the most powerful

of the three—destructuring. You’ll see just how powerful this mini-language within

Clojure can be toward developing elegant and often beautiful solutions.

Download from Wow! eBook <www.wowebook.com>

Destructuring

47

3.3

Destructuring

In the previous section, we briefly described Clojure’s destructuring facility as a mini-

language embedded within Clojure. Destructuring allows us to positionally bind locals

based on an expected form for a composite data structure. In this section, we’ll

explore how destructuring can be used to pull apart composite structures into bind-

ings through the lens of a simple rolodex example project.

PATTERN MATCHING Destructuring is loosely related to pattern matching

found in Haskell, KRC, or Scala, but much more limited in scope. For more

full-featured pattern matching in Clojure, consider using http://

github.com/dcolthorp/matchure, which may in the future be included in contrib as clojure.core.match.

3.3.1

Your assignment, should you choose to accept it

You’ve heard that the rolodex project has been overdue, but now every developer

assigned to it is out sick. The QA team is ready to go, but one function is still missing

and it’s a show-stopper. You’re told to drop everything and write the function ASAP.

The design? Take a vector of length 3 that represents a person’s first, middle, and

last names and return a string that will sort in the normal way, like “Steele, Guy Lewis”.

What are you waiting for? Why aren’t you done yet?!?!

(def guys-whole-name ["Guy" "Lewis" "Steele"])

(str (nth guys-whole-name 2) ", "

(nth guys-whole-name 0) " "

(nth guys-whole-name 1)))

;=> "Steele, Guy Lewis"

Alas, by the time you’ve finished typing guys-whole-name for the fourth time, it’s too

late. The customers have cancelled their orders, and the whole department is bound

to be downsized.

If only you’d known about destructuring.

Okay, so you’re not likely to lose your job because your function is twice as many

lines as it needs to be, but still that’s a lot of code repeated in a pretty small function.

And using index numbers instead of named locals makes the purpose of the function

more obscure than necessary.

Destructuring solves both these problems by allowing you to place a collection of

names in a binding form where normally you’d put just a single name. One kind of

binding form is the list of parameters given in a function definition.

3.3.2

Destructuring with a vector

So let’s try that again, but use destructuring with let to create more convenient locals

for the parts of Guy’s name:

(let [[f-name m-name l-name] guys-whole-name]

(str l-name ", " f-name " " m-name))

Download from Wow! eBook <www.wowebook.com>

48

CHAPTER 3 Dipping our toes in the pool

Positional destructuring

This positional destructuring doesn’t work on maps and sets because they’re not

logically3 aligned sequentially. Thankfully, positional destructuring will work with

Java’s java.util.regex.Matcher and anything implementing the CharSequence

and java.util.RandomAccess interfaces.

This is the simplest form of destructuring, where you want to pick apart a sequential

thing (a vector of strings in this case, though a list or other sequential collection

would work as well), giving each item a name.3

We don’t need it here, but we can also use an ampersand in a destructuring vector

to indicate that any remaining values of the input should be collected into a (possibly

lazy) seq:

(let [[a b c & more] (range 10)]

(println "a b c are:" a b c)

(println "more is:" more))

; a b c are: 0 1 2

; more is: (3 4 5 6 7 8 9)

;=> nil

Here the locals a, b, and c are created and bound to the first three values of the range.

Because the next symbol is an ampersand, the remaining values are made available as

a seq bound to more. The name more is pretty common for this purpose, but isn’t spe-

cial—you’ll often see etc or xs instead, or some other name that makes sense in a par-

ticular context.

The final feature of vector destructuring is :as, which can be used to bind a local

to the entire collection. It must be placed after the & local, if there is one, at the end of

the destructuring vector:

(let [range-vec (vec (range 10))

[a b c & more :as all] range-vec]

(println "a b c are:" a b c)

(println "more is:" more)

(println "all is:" all))

; a b c are: 0 1 2

; more is: (3 4 5 6 7 8 9)

; all is: [0 1 2 3 4 5 6 7 8 9]

;=> nil

We made range-vec a vector in this example, and the directive :as binds the input

collection as-is, entirely unmolested, so that the vector stays a vector. This is in contrast

to &, which bound more to a seq, not a vector.

3 Technically, positional destructuring might make sense with sorted sets and maps, but alas it doesn’t operate

as such.

Download from Wow! eBook <www.wowebook.com>

Destructuring

49

3.3.3

Destructuring with a map

Perhaps passing a name as a three-part vector wasn’t a good idea in the first place. It

might be better stored in a map:

(def guys-name-map

{:f-name "Guy" :m-name "Lewis" :l-name "Steele"})

But now we can’t use a vector to pick it apart effectively. Instead, we use a map:

(let [{f-name :f-name, m-name :m-name, l-name :l-name} guys-name-map]

(str l-name ", " f-name " " m-name))

A couple things about this example may jump out at you. One might be that it still

seems repetitive—we’ll get to that in a moment.

Another might be that it looks a bit unexpected to have the keywords like :f-name

on the right-hand side of each pair even though the input map had keywords on the

left. There are a couple reasons for that. The first is to help keep the pattern of the

name on the left getting the value specified by the thing on the right. That is, the new

local f-name gets the value looked up in the map by the key :f-name, just as the whole

map gets its value from guys-name-map in the earlier def form.

The second reason is because it allows us to conjure up other destructuring fea-

tures by using forms that would otherwise make no sense. Because the item on the left

of each pair will be a new local name, it must be a symbol or possibly a nested destruc-

turing form. But one thing it can’t be is a keyword, unless the keyword is a specially

supported feature such as :keys, :strs, :syms, :as, and :or.

We’ll discuss the :keys feature first because it nicely handles the repetitiveness we

mentioned earlier. It allows us to rewrite our solution like this:

(let [{:keys [f-name m-name l-name]} guys-name-map]

(str l-name ", " f-name " " m-name))

So by using :keys instead of a binding form, we’re telling Clojure that the next form

will be a vector of names that it should convert to keywords such as :f-name in order

to look up their values in the input map. Similarly, if we had used :strs, Clojure

would be looking for items in the map with string keys such as "f-name", and :syms

would indicate symbol keys.

The directives :keys, :strs, :syms, and regular named bindings can appear in

any combination and in any order. But sometimes you’ll want to get at the original

map—in other words, the keys that you didn’t name individually by any of the meth-

ods just described. For that, you want :as, which works just like it does with vector

destructuring:

(let [{f-name :f-name, :as whole-name} guys-name-map]

whole-name)

;=> {:f-name "Guy", :m-name "Lewis", :l-name "Steele"}

If the destructuring map looks up a key that’s not in the source map, it’s normally

bound to nil, but you can provide different defaults with :or:

Download from Wow! eBook <www.wowebook.com>

50

CHAPTER 3 Dipping our toes in the pool

(let [{:keys [title f-name m-name l-name], :or {title "Mr."}} guys-name-map]

(println title f-name m-name l-name))

; Mr. Guy Lewis Steele

;=> nil

ASSOCIATIVE DESTRUCTURING

One final technique worth mentioning is associative destructuring. Using a map to

define a number of destructure bindings isn’t limited to maps. We can also destruc-

ture a vector by providing a map declaring the local name as indices into them, as

shown:

(let [{first-thing 0, last-thing 3} [1 2 3 4]]

[first-thing last-thing])

;=> [1 4]

We’ll explore associative destructuring later in section 6.1 when we discuss Clojure’s

support for named structures. You’ve seen the shapes that destructuring takes within

the let form, but you’re not limited to that exclusively, as we’ll explore next.

3.3.4

Destructuring in function parameters

All the preceding examples use let to do their destructuring, but exactly the same

features are available in function parameters. Each function parameter can destruc-

ture a map or sequence:

(defn print-last-name [{:keys [l-name]}]

(println l-name))

(print-last-name guys-name-map)

; Steele

;=> nil

Note that function arguments can include an ampersand as well, but this isn’t the

same as destructuring. Instead, that’s part of their general support for multiple func-

tion bodies, each with its own number of parameters.

3.3.5

Destructuring versus accessor methods

In many object-oriented languages, you might create new classes to manage your

application data objects, each with its own set of getter and setter methods. It’s idiom-

atic in Clojure to instead build your application objects by composing maps and vec-

tors as necessary. This makes destructuring natural and straightforward. So anytime

you find that you’re calling nth on the same collection a few times, or looking up con-

stants in a map, or using first or next, consider using destructuring instead.

Now that we’ve made it through the cursory introduction to Clojure, let’s take

some time to pair-program (Williams 2002). In the next section, we’ll take many of

the bare necessities that you’ve just learned and walk through the creation of a couple

interesting functions for drawing pretty pictures within Clojure’s REPL.

Download from Wow! eBook <www.wowebook.com>

Using the REPL to experiment

51

3.4

Using the REPL to experiment

Most software development projects include a stage where you’re not sure what needs

to happen next. Perhaps you need to use a library or part of a library you’ve never

touched before. Or perhaps you know what your input to a particular function will be,

and what the output should be, but you aren’t sure how to get from one to other. In

more static languages, this can be time-consuming and frustrating; but by leveraging

the power of the Clojure REPL, the interactive command prompt, it can actually be fun.

3.4.1

Experimenting with seqs

Say someone suggests to you that coloring every pixel of a canvas with the xor of its x

and y coordinates might produce an interesting image. It shouldn’t be too hard, so

you can jump right in. You’ll need to perform an operation on every x and y in a pair

of ranges. Do you know how range works?

(range 5)

;=> (0 1 2 3 4)

That should do nicely for one coordinate. To nest seqs, for often does the trick. But

again, rather than writing code and waiting until you have enough to warrant compil-

ing and testing, you can just try it:

(for [x (range 2) y (range 2)] [x y])

;=> ([0 0] [0 1] [1 0] [1 1])

There are the coordinates that will form your input. Now you need to xor them:

(xor 1 2)

;=> java.lang.Exception: Unable to resolve symbol: xor in this context

Bother—no function named xor. Fortunately, Clojure provides find-doc, which

searches not just function names but also their doc strings for the given term:

(find-doc "xor")

; -------------------------

; clojure.core/bit-xor

; ([x y])

; Bitwise exclusive or

;=> nil

So the function you need is called bit-xor:

(bit-xor 1 2)

;=> 3

Perfect! Now you want to adjust your earlier for form to return the bit-xor along

with the x and y. The easiest way to do this will depend on what tool is hosting your

REPL. In many, you can just press the up-arrow key on your keyboard a couple of times

to bring back the earlier for form. You’re not going to want to retype things to make

minor adjustments, so take a moment right now to figure out a method you like that

will allow you to make a tweak like this by inserting the bit-xor call:

Download from Wow! eBook <www.wowebook.com>

52

CHAPTER 3 Dipping our toes in the pool

(for [x (range 2) y (range 2)] [x y (bit-xor x y)])

;=> ([0 0 0] [0 1 1] [1 0 1] [1 1 0])

That looks about right. Now you’re about to shift gears to pursue the graphics side of

this problem, so tuck that bit of code away in a function so it’ll be easy to use later:

(defn xors [max-x max-y] (for [x (range max-x) y (range max-y)] [x y (bit-

xor x y)]))

(xors 2 2)

;=> ([0 0 0] [0 1 1] [1 0 1] [1 1 0])

You might even save that into a .clj file somewhere, if you haven’t already.

3.4.2

Experimenting with graphics

Clojure’s REPL isn’t just for playing around; it’s also great for experimenting with Java

libraries. We believe that there’s no better environment for exploring a Java API than

Clojure’s REPL. To illustrate, poke around with java.awt, starting with a Frame:

(def frame (java.awt.Frame.))

;=> #'user/frame

That should’ve created a Frame, but no window appeared. Did it work at all?

frame

;=> #<Frame java.awt.Frame[frame0,0,22,0x0,invalid,hidden,...]>

Well, you have a Frame object, but perhaps the reason you can’t see it is hinted at by

the word hidden in the #<Frame...> printout. Perhaps the Frame has a method you

need to call to make it visible. One way to find out would be to check the Javadoc of

the object, but because you’re at the REPL already, let’s try something else. You’ve

already seen how the for macro works, so maybe you can check a class for which

methods it has to see whether one that you can use is available:

(for [method (seq (.getMethods java.awt.Frame))

:let [method-name (.getName method)]

:when (re-find #"Vis" method-name)]

method-name)

;=> ("setVisible" "isVisible")

The for macro takes a :let flag and bindings vector that works similarly to the let

special form that you use to bind the local method-name to the result of calling the

method .getName on each method in turn. The :when is used to limit the elements

used in its body to only those that return a truthy value in the expression after the

directive. Using these directives allows you to iterate through the methods and build a

seq of those whose names match a regular expression #"Vis". We’ll cover Clojure’s

regular expression syntax in section 3.5.

THE CONTRIB FUNCTION SHOW The clojure-contrib library also has a function

show in the clojure.contrib.repl-utils namespace that allows for more

useful printouts of class members than we show using for.

Your query returned two potential methods, so try out each of them:

Download from Wow! eBook <www.wowebook.com>

Using the REPL to experiment

53

(.isVisible frame)

;=> false

That’s false, as you might’ve suspected. Will setting it to true make any difference?

(.setVisible frame true)

;=> nil

It did, but it’s so tiny! Not to worry, as a Frame class also has a .setSize method that

you can use:

(.setSize frame (java.awt.Dimension. 200 200))

;=> nil

And up pops a blank window for you to draw on. At this point, we’ll guide you

through the rest of this section, but keep in mind that Java’s official API might be of

interest should you choose to extend the example program.

THE JAVADOC FUNCTION As of Clojure 1.2, a javadoc function is automati-

cally available at the REPL to query and view official API documentation:

(javadoc frame)

This should return a string corresponding to a URL and open a browser win-

dow for just the right page of documentation. Prior to Clojure 1.2, this func-

tion was in clojure.contrib.repl-utils.

What you need to draw into your Frame is its graphics context, which can be fetched

as shown:

(def gfx (.getGraphics frame))

;=> #'user/gfx

Then, to actually draw, you can try out the fillRect method of that graphics context.

If you’re trying this yourself, make sure the blank window is positioned so that it’s

unobscured while you’re typing into your REPL:

(.fillRect gfx 100 100 50 75)

And just like that, you’re drawing on the screen interactively. You should see a single

black rectangle in the formerly empty window. Exciting, isn’t it? You could be a kid

playing with turtle graphics for the first time, it’s so much fun. But what it needs now is

a dash of color:

(.setColor gfx (java.awt.Color. 255 128 0))

(.fillRect gfx 100 150 75 50)

Now there should be an orange rectangle as well. Perhaps the coloring would make

Martha Stewart cry, but you now have tried out all the basic building blocks you’ll

need to complete the original task: you have a function that returns a seq of coordi-

nates and their xor values, you have a window you can draw into, and you know how to

draw rectangles of different colors. Bear in mind that if you move the actual frame

with the mouse, your beautiful graphics will disappear. This is just an artifact of this

limited experiment and can be avoided using the full Java Swing capabilities.

Download from Wow! eBook <www.wowebook.com>

54

CHAPTER 3 Dipping our toes in the pool

3.4.3

Putting it all together

What’s left to do? Use the graphics functions you just saw to draw the xor values you

created earlier:

(doseq [[x y xor] (xors 200 200)]

(.setColor gfx (java.awt.Color. xor xor xor))

(.fillRect gfx x y 1 1))

The xors function you created earlier generates a seq of

vectors, if you remember, where each vector has three

elements: the x and y for your coordinates and the xor

value that goes with them. The first line here uses

destructuring to assign each of those three values to new

locals x, y, and xor, respectively.

The second line sets the “pen” color to a gray level

based on the xor value, and the final line draws a single-

pixel rectangle at the current coordinates. The resulting

Figure 3.1 Visualization of

graphic is shown in figure 3.1.

xor. This is the graphic drawn

But just because you’ve succeeded doesn’t mean you

by the six or so lines of code

have to quit. You’ve built up some knowledge and a bit of

we’ve looked at so far—a

visual representation of

a toolbox, so why not play with it a little?

Clojure’s bit-xor function.

3.4.4

When things go wrong

For example, the pattern appears to cut off in the middle—perhaps you’d like to see a

bit more. Re-enter that last expression, but this time try larger limits:

(doseq [[x y xor] (xors 500 500)]

(.setColor gfx (java.awt.Color. xor xor xor))

(.fillRect gfx x y 1 1))

; java.lang.IllegalArgumentException:

; Color parameter outside of expected range: Red Green Blue

Whoops. Something went wrong, but what exactly? This gives you a perfect opportu-

nity to try out one final REPL tool. When an exception is thrown from something you

try at the REPL, the result is stored in a Var named *e. This allows you to get more

detail about the expression, such as the stack trace:

(.printStackTrace *e)

; java.lang.IllegalArgumentException: Color parameter outside of

; expected range: Red Green Blue

; at clojure.lang.Compiler.eval(Compiler.java:4639)

; at clojure.core$eval__5182.invoke(core.clj:1966)

; at clojure.main$repl__7283$read_eval_print__7295.invoke(main.clj:180)

; ...skipping a bit here...

; Caused by: java.lang.IllegalArgumentException: Color parameter

; outside of expected range: Red Green Blue

; at java.awt.Color.testColorValueRange(Color.java:298)

; at java.awt.Color.<init>(Color.java:382)

; ...skipping a bit more...

; ... 11 more

;=> nil

Download from Wow! eBook <www.wowebook.com>

Using the REPL to experiment

55

That’s a lot of text, but don’t panic. Learning to read Java stack traces will be useful, so

let’s pick it apart.

The first thing to understand is the overall structure of the trace—there are two

“causes.” The original or root cause of the exception is listed last—this is the best

place to look first.4 The name and text of the exception there are the same as the

REPL printed for us in the first place, though they won’t always be. So let’s look at that

next line:

at java.awt.Color.testColorValueRange(Color.java:298)

Like most lines in the stack trace, this has four parts: the name of the class, the name

of the method, the filename, and finally the line number:

at <class>.<method or constructor>(<filename>:<line>)

In this case, the function name is testColorValueRange, which is defined in Java’s

own Color.java file. Unless this means more to you than it does to us, let’s move on to

the next line:

at java.awt.Color.<init>(Color.java:382)

It appears that it was the Color’s constructor (called <init> in stack traces) that called

that test function you saw earlier. So now the picture is pretty clear—when you con-

structed a Color instance, it checked the values you passed in, decided they were

invalid, and threw an appropriate exception.

If this weren’t enough, you could continue walking down the stack trace until the

line

... 11 more

This is your cue to jump up to the cause listed before this one to find out what the

next 11 stack frames were.

To fix your invalid Color argument, you can just adjust the xors function to return

only legal values using the rem function, which returns the remainder so you can keep

the results under 256:

(defn xors [xs ys]

(for [x (range xs) y (range ys)]

[x y (rem (bit-xor x y) 256)]))

Note that you’re redefining an existing function here. This is perfectly acceptable and

well-supported behavior. Before moving on, create a function that takes a graphics

object and clears it:

(defn clear [g] (.clearRect g 0 0 200 200))

Calling (clear gfx) will clear the frame, allowing the doseq form you tried before to

work perfectly.

4

This is a runtime exception, the most common kind. If you misuse a macro or find a bug in one, you may see

compile-time exceptions. The trace will look similar but will have many more references to Compiler.java. For

these traces, the most recent exception (listed first) may be the only one that identifies the filename and line

number in your code that’s at fault.

Download from Wow! eBook <www.wowebook.com>

56

CHAPTER 3 Dipping our toes in the pool

3.4.5

Just for fun

The bit-xor function does produce an interesting image, but perhaps you wonder

what other functions might look like. Try adding another parameter to xors so that

you can pass in whatever function you’d like to look at. Because it’s not just bit-xor

anymore, change the name while you’re at it:

(defn f-values [f xs ys]

(for [x (range xs) y (range ys)]

[x y (rem (f x y) 256)]))

You might as well wrap your call to setSize, clear, and the doseq form in a function

as well:

(defn draw-values [f xs ys]

(clear gfx)

(.setSize frame (java.awt.Dimension. xs ys))

(doseq [[x y v] (f-values f xs ys)]

(.setColor gfx (java.awt.Color. v v v))

(.fillRect gfx x y 1 1)))

This allows you to try out different functions and ranges quite easily. More nice exam-

ples are shown in figure 3.2, resulting from the following:

(draw-values bit-and 256 256)

(draw-values + 256 256)

(draw-values * 256 256)

If this were the beginning or some awkward middle stage of a large project, you’d

have succeeded in pushing past this troubling point and could now take the functions

you’ve built and drop them into the larger project.

By trying everything out at the REPL, you’re encouraged to try smaller pieces

rather than larger ones. The smaller the piece, the shorter the distance down an

incorrect path you’re likely to go. Not only does this reduce the overall development

time, but it provides developers more frequent successes that can help keep morale

and motivation high through even

tough stages of a project. But trial-and-

error exploration isn’t enough. An

intuitive basis in Clojure is also

needed to become highly effective.

Throughout this book, we’ll help you

to build your intuition in Clojure Figure 3.2 Three possible results from draw-

values. The draw-values function you’ve written

through discussions of its idioms and can be used to create a variety of graphics. Here are

its motivating factors and rationale.

examples, from left to right, of bit-and, +, and *.

3.5

Summary

We started slowly in this chapter in order to take a breather from the sprint that was

chapter 2. Truthiness in Clojure observes a simple rule: every object is true all the

time, unless it’s nil or false. Second, in many Lisp-like languages, the empty list ()

Download from Wow! eBook <www.wowebook.com>

Summary

57

and the truth value nil are analogous—this is known as nil-punning—but in Clojure

this isn’t the case. Instead, idiomatic Clojure employs the (seq (rest _)) idiom in

the form of the next function to provide a mechanism fostering “form follows func-

tion” and also to eliminate errors associated with falsety/empty-seq disparity. Finally,

destructuring provides a powerful mechanism, a mini-language for binding if you will,

for partially or entirely pulling apart the constituent components of composite types.

Our trek through the REPL illustrated the power in having the whole language

(Graham 2001) at your disposal. As a Clojure programmer, you’ll spend a lot of time

in the REPL, and pretty soon you won’t know how you lived without it.

In the next chapter, we’ll touch on matters concerning Clojure’s seemingly inno-

cent scalar data types. Although in most cases these scalars will expose powerful pro-

gramming techniques, be forewarned: as you’ll see, the picture isn’t always rosy.

Download from Wow! eBook <www.wowebook.com>

Download from Wow! eBook <www.wowebook.com>

Part 2

Data types

Clojure has squirreled away interesting tidbits even among its data types.

The scalar types include some less common items such as keywords and rational

numbers, and the composite types are all immutable. In this part, we’ll explore

all of them in detail.

Download from Wow! eBook <www.wowebook.com>

Download from Wow! eBook <www.wowebook.com>

On scalars

It requires a very unusual mind to

undertake the analysis of the obvious.

—Alfred North Whitehead

This chapter covers

 Understanding precision

 Trying to be rational

 When to use keywords

 Symbolic resolution

 Regular expressions—the second problem

So far, we’ve covered a somewhat eclectic mix of theoretical and practical concerns.

This brings us now to a point where we can dive deeper into a fundamental topic:

how Clojure deals with scalar values, including numeric, symbolic, and regular

expression values, and how they behave as data and sometimes as code.

A scalar data type is one that can only hold one value at a time of a number, sym-

bol, keyword, string, or character. Most of the use cases for Clojure’s scalar data

types will be familiar to you. But there are some nuances that should be observed.

Clojure’s scalar data types exist in an interesting conceptual space. Because of its

symbiotic nature, some of the scalar type behaviors walk a conceptual line between

61

Download from Wow! eBook <www.wowebook.com>

62

CHAPTER 4 On scalars

pure Clojure semantics and host semantics. This chapter provides a rundown of some

of the idiomatic uses of Clojure’s scalar data types as well as some pitfalls that you

might encounter. In most cases, Clojure will shield you from the quirks of its host, but

there are times when they’ll demand attention. Clojure’s scalar types have the poten-

tial to act like Sybil—sweet and kind one moment, vicious and vile the next—requir-

ing some thought to handle properly. We’ll also talk about this duality and address its

limitations and possible mitigation techniques. Additionally, we’ll address the age-old

topic of Lisp-1 versus Lisp-2 implementations and how Clojure approaches the matter.

Finally, we’ll talk briefly about Clojure’s regular expression literals and how they’re

typically used.

We’ll first cover matters of numerical precision and how the Java Virtual Machine

works to thwart your attempts at mathematical nirvana.

4.1

Understanding precision

Numbers in Clojure are by default as precise1 as they need to be. Given enough mem-

ory, you could store the value of Pi accurately up to a billion places and beyond; in

practice, values that large are rarely needed. But it’s sometimes important to provide

perfect accuracy at less-precise values. When dealing with raw Clojure functions and

forms, it’s a trivial matter to ensure such accuracy; it’s handled automatically. Because

Clojure encourages interoperability with its host platform, the matter of accuracy

becomes less than certain. This section will talk about real matters of precision related

to Clojure’s support for the Java Virtual Machine. As it pertains to programming lan-

guages,2 numerical precision is proportional to the mechanisms used for storing

numerical representations. The Java language specification describes the internal rep-

resentation of its primitive types thus limiting their precision. Depending on the class

of application specialization, a programmer could go an entire career and never be

affected by Java’s precision limitations. But many industries require perfect accuracy

of arbitrarily precise computations, and it’s here that Clojure can provide a great

boon; but with this power come some pointy edges, as we’ll discuss shortly.

4.1.1

Truncation

Truncation refers to the limiting of accuracy for a floating-point number based on a

deficiency in the corresponding representation. When a number is truncated, its pre-

cision is limited such that the maximum number of digits of accuracy is bound by the

number of bits that can “fit” into the storage space allowed by its representation. For

floating-point values, Clojure truncates by default. Therefore, if high precision is

required for your floating-point operations, then explicit typing is required, as seen

with the use of the M literal in the following:

1

In a future version of Clojure, this arbitrary precision won’t be the default, but will require explicit flagging

(with the aforementioned M for decimal numbers and N for longs). Additionally, overflow of primitive num-

bers will always signal an exception.

2

As opposed to arithmetic precision.

Download from Wow! eBook <www.wowebook.com>

Understanding precision

63

(let [imadeuapi 3.14159265358979323846264338327950288419716939937M]

(println (class imadeuapi))

imadeuapi)

; java.math.BigDecimal

;=> 3.14159265358979323846264338327950288419716939937M

(let [butieatedit 3.14159265358979323846264338327950288419716939937]

(println (class butieatedit))

butieatedit)

; java.lang.Double

;=> 3.141592653589793

As we show, the local butieatedit is truncated because the default Java double type is

insufficient. On the other hand, imadeuapi uses Clojure’s literal notation, a suffix

character M, to declare a value as requiring arbitrary decimal representation. This is

one possible way to mitigate truncation for a immensely large range of values, but as

we’ll explore in section 4.2, it’s not a guarantee of perfect precision.

4.1.2

Promotion

Clojure is able to detect when overflow occurs, and will promote the value to a numer-

ical representation that can accommodate larger values. In many cases, promotion

results in the usage of a pair of classes used to hold exceptionally large values. This pro-

motion within Clojure is automatic, as the primary focus is first correctness of numeri-

cal values, then raw speed. It’s important to remember that this promotion will occur,

as shown in the following listing, and your code should accommodate3 this certainty.

Listing 4.1 Automatic promotion in Clojure

(def clueless 9)

(class clueless)

;=> java.lang.Integer

(class (+ clueless 9000000000000000))

;=> java.lang.Long

(class (+ clueless 90000000000000000000))

;=> java.math.BigInteger

(class (+ clueless 9.0))

;=> java.lang.Double

Java itself has a bevy of contexts under which automatic type conversion will occur, so

we advise you to familiarize yourself with those (Lindholm 1999) when dealing with

Java native libraries.

3 In the example, it’s important to realize that the actual class of the value is changing, so any functions or meth-

ods reliant on specific types might not work as expected.

Download from Wow! eBook <www.wowebook.com>

64

CHAPTER 4 On scalars

4.1.3

Overflow

Integer and long values in Java are subject to overflow errors. When an integer calcu-

lation results in a value that’s larger than 32 bits of representation will allow, the bits of

storage will “wrap” around. When you’re operating in Clojure, overflow won’t be an

issue for most cases, thanks to promotion. But when dealing with numeric operations

on primitive types, overflow can occur. Fortunately in these instances an exception

will occur rather than propagating inaccuracies:

(+ Integer/MAX_VALUE Integer/MAX_VALUE)

;=> java.lang.ArithmeticException: integer overflow

Clojure provides a class of unchecked integer and long mathematical operations that

assume that their arguments are primitive types. These unchecked operations will

overflow if given excessively large values:

(unchecked-add (Integer/MAX_VALUE) (Integer/MAX_VALUE))

;=> -2

You should take care with unchecked operations, because there’s no way to detect

overflowing values and no reliable way to return from them. Use the unchecked func-

tions only when overflow is desired.

4.1.4

Underflow

Underflow is the inverse of overflow, where a number is so small that its value collapses

into zero. Simple examples of underflow for float and doubles can be demonstrated:

(float 0.0000000000000000000000000000000000000000000001)

;=> 0.0

1.0E-430

;=> 0.0

Underflow presents a danger similar to overflow, except that it occurs only with

floating-point numbers.

4.1.5

Rounding errors

When the representation of a floating-point value isn’t sufficient for storing its actual

value, then rounding errors will occur (Goldberg 1994). Rounding errors are an espe-

cially insidious numerical inaccuracy, as they have a habit of propagating throughout a

computation and/or build over time, leading to difficulties in debugging. There’s a

famous case involving the failure of a Patriot missile caused by a rounding error, result-

ing in the death of 28 U.S. soldiers in the first Gulf War (Skeel 1992). This occurred

due to a rounding error in the representation of a count register’s update interval. The

timer register was meant to update once every 0.1 seconds, but because the hardware

couldn’t represent 0.1 directly, an approximation was used instead. Tragically, the

approximation used was subject to rounding error. Therefore, over the course of 100

hours, the rounding accumulated into a timing error of approximately 0.34 seconds.

Download from Wow! eBook <www.wowebook.com>

Trying to be rational

65

Listing 4.2 Illustrating the Patriot missile tragedy

(let [aprox-interval (/ 209715 2097152)

Patriot’s approx 0.1

actual-interval (/ 1 10)

Clojure’s accurate 0.1

hours (* 3600 100 10)

actual-total (double (* hours actual-interval))

aprox-total (double (* hours aprox-interval))]

(- actual-total aprox-total))

;=> 0.34332275390625

In the case of the Patriot missile, the deviation of 0.34 seconds was enough to cause a

catastrophic software error, resulting in its ineffectiveness. When human lives are at

stake, the inaccuracies wrought from rounding errors are unacceptable. For the most

part, Clojure will be able to maintain arithmetic accuracies within a certain range, but

you shouldn’t take for granted that such will be the case when interacting with Java

libraries.

One way to contribute to rounding errors is to introduce doubles and floats into

an operation. In Clojure, any computation involving even a single double will result in

a value that’s a double:

(+ 0.1M 0.1M 0.1M 0.1 0.1M 0.1M 0.1M 0.1M 0.1M 0.1M)

;=> 0.9999999999999999

Can you spot the double?

This discussion was Java-centric, but Clojure’s ultimate goal is to be platform-

agnostic, and the problem of numerical consistency across platforms is a nontrivial

matter. It’s still unknown whether the preceding points will be universal across host

platforms, so please bear in mind that they should be reexamined when using Clojure

outside the context of the JVM. Now that we’ve identified the root issues when dealing

with numbers in Clojure, we’ll dive into a successful mitigation technique for dealing

with them—rationals.

4.2

Trying to be rational

Clojure provides a data type representing a rational number, and all of its core mathe-

matical functions operate with rational numbers. Clojure’s rationals allow for arbi-

trarily large numerators and denominators. We won’t go into depth about the

limitations of floating-point operations, but the problem can be summarized simply.

Given a finite representation of an infinitely large set, a determination must be made

which finite subset is represented. In the case of standard floating-point numbers as

representations of real numbers, the distribution of represented numbers is logarith-

mic (Kuki 1973) and not one-for-one. What does this mean in practice? It means that

requiring more accuracy in your floating-point operations increases the probability

that the corresponding representation won’t be available. In these circumstances,

you’ll have to settle for approximations. But Clojure’s rational number type provides a

way to retain perfect accuracy when needed.

Download from Wow! eBook <www.wowebook.com>

66

CHAPTER 4 On scalars

4.2.1

Why be rational?

Of course, Clojure provides a decimal type that’s boundless relative to your computer

memory, so why wouldn’t you just use those? In short, you can, but decimal operations

can be easily corrupted, especially when working with existing Java libraries (Kahan

1998) taking and returning primitive types. Additionally, in the case of Java, its under-

lying BigDecimal class is finite in that it uses a 32-bit integer to represent the number

of digits to the right of the decimal place. This can represent an extremely large range

of values perfectly, but it’s still subject to error:

1.0E-430000000M

;=> 1.0E-430000000M

1.0E-4300000000M

;=> java.lang.RuntimeException: java.lang.NumberFormatException

Even if you manage to ensure that your BigDecimal values are free from floating-point

corruption, you can never protect them from themselves. At some point or another, a

floating-point calculation will encounter a number such as 2/3 that will always require

rounding, leading to subtle, yet propagating errors. Finally, floating-point arithmetic

is neither associative nor distributive, which may lead to the shocking results shown in

this listing.

Listing 4.3 Floating-point arithmetic isn’t associative or distributive.

(def a 1.0e50)

(def b -1.0e50)

(def c 17.0e00)

(+ (+ a b) c)

;=> 17.0

Associativity should

(+ a (+ b c))

guarantee 17.0 also

;=> 0.0

(let [a (float 0.1)

b (float 0.2)

c (float 0.3)]

(=

(* a (+ b c))

Distributive should

(+ (* a b) (* a c))))

guarantee equality

;=> false

Therefore, for absolutely precise calculations, rationals are the best choice.4

4.2.2

How to be rational

Aside from the rational data type, Clojure provides functions that can help to main-

tain your sanity: ratio?, rational?, and rationalize. Additionally, taking apart ratio-

nals is also a trivial matter.

4 In the case of irrational numbers like Pi, all bets are off.

Download from Wow! eBook <www.wowebook.com>

Trying to be rational

67

The best way to ensure that your calculations remain as accurate as possible is to

ensure that they’re all done using rational numbers. As shown in the following listing,

the shocking results from using floating-point numbers have been eliminated.

Listing 4.4 Being rational preserves associativity and distributive natures.

(def a (rationalize 1.0e50))

(def b (rationalize -1.0e50))

(def c (rationalize 17.0e00))

(+ (+ a b) c)

;=> 17

(+ a (+ b c))

Associativity

;=> 17

preserved

(let [a (rationalize 0.1)

b (rationalize 0.2)

c (rationalize 0.3)]

(=

(* a (+ b c))

Distributive

(+ (* a b) (* a c))))

nature preserved

;=> true

To ensure that your numbers remain rational, you can use rational? to check

whether a given number is one and then use rationalize to convert it to one. There

are a few rules of thumb to remember if you want to maintain perfect accuracy in your

computations:

1

Never use Java math libraries unless they return results of BigDecimal, and even

then be suspicious.

2

Don’t rationalize values that are Java float or double primitives.

3

If you must write your own high-precision calculations, do so with rationals.

4

Only convert to a floating-point representation as a last resort.

Finally, you can extract the constituent parts of a rational using the numerator and

denominator functions:

(numerator (/ 123 10))

;=> 123

(denominator (/ 123 10))

;=> 10

You might never need perfect accuracy in your calculations. When you do, Clojure pro-

vides tools for maintaining sanity, but the responsibility to maintain rigor lies with you.

4.2.3

Caveats of rationality

Like any tool, Clojure’s rational type is a double-edged sword. The calculation of ratio-

nal math, though accurate, isn’t nearly as fast as with floats or doubles. Each operation

in rational math has an overhead cost (such as finding the least common denomina-

tor) that should be accounted for. It does you no good to use rational operations if

speed is a primary concern above accuracy.

Download from Wow! eBook <www.wowebook.com>

68

CHAPTER 4 On scalars

That covers the numerical scalars, so we’ll move on to two data types that you may

not be familiar with unless you happen to come from a background in the Lisp family

of languages: keywords and symbols.

4.3

When to use keywords

The purpose of Clojure keywords, or symbolic identifiers, can sometimes lead to confu-

sion for first-time Clojure programmers, because their analogue isn’t often found5 in

other languages. This section will attempt to alleviate the confusion and provide some

tips for how keywords are typically used.

4.3.1

How are keywords different from symbols?

Keywords always refer to themselves. What this means is that the keyword :magma

always has the value :magma, whereas the symbol ruins may refer to any legal Clojure

value or reference.

AS KEYS

Because keywords are self-evaluating and provide fast equality checks, they’re almost

always used in the context of map keys. An equally important reason to use keywords

as map keys is that they can be used as functions, taking a map as an argument, to per-

form value lookups:

(def population {:zombies 2700, :humans 9})

(:zombies population)

;=> 2700

(println (/ (:zombies population)

(:humans population))

"zombies per capita")

; 300 zombies per capita

This leads to much more concise code.

AS ENUMERATIONS

Often, Clojure code will use keywords as enumeration values, such as :small,

:medium, and :large. This provides a nice visual delineation within the source code.

AS MULTIMETHOD DISPATCH VALUES

Because keywords are used often as enumerations, they’re ideal candidates for dis-

patch values for multimethods, which we’ll explore in more detail in section 9.1.

AS DIRECTIVES

Another common use for keywords is to provide a directive to a function, multi-

method, or macro. A simple way to illustrate this is to imagine a simple function pour,

shown in listing 4.5, that takes two numbers and returns a lazy sequence of the range

of those numbers. But there’s also a mode for this function that takes a keyword :tou-

jours, which will instead return an infinite lazy range starting with the first number

and continuing “forever.”

5 Ruby has a symbol type that acts, looks, and is used similarly to Clojure keywords.

Download from Wow! eBook <www.wowebook.com>

When to use keywords

69

Listing 4.5 Using a keyword as a function directive

(defn pour [lb ub]

(cond

(= ub :toujours) (iterate inc lb)

:else (range lb ub)))

(pour 1 10)

;=> (1 2 3 4 5 6 7 8 9)

(pour 1 :toujours)

; ... runs forever

An illustrative bonus with pour is that the macro cond itself uses a directive :else to

mark the default conditional case. In this case, cond uses the fact that the keyword

:else is truthy; any keyword (or truthy value) would’ve worked just as well.

4.3.2

Qualifying your keywords

Keywords don’t belong to any specific namespace, although they may appear to if

namespace qualification is used:

::not-in-ns

;=> :user/not-in-ns

The prefix portion of the keyword marked as :user/ only looks like it’s denoting an

owning namespace; in fact, it’s a prefix gathered from the current namespace by the

Clojure reader. Observe the use of arbitrary prefixing:

(ns another)

:user/in-another

;=> :user/in-another

:haunted/name

;=> :haunted/name

In the first case, we created a namespace another and created a keyword :user/in-

another that appears to belong to the user namespace, but in fact is prefixed. In the

second example, we created a keyword :haunted/name showing that the prefix doesn’t

have to belong to a namespace at all, given that one named haunted certainly doesn’t

exist. But the fact that keywords aren’t members of any given namespace doesn’t mean

that namespace-qualifying them is pointless. Instead, it’s often more clear to do so,

especially when a namespace aggregates a specific functionality and its keywords are

meaningful in that context.

Separating the plumbing from the domain

Within a namespace named crypto, the keywords ::rsa and ::blowfish make

sense as being namespace-qualified. Likewise, should we create a namespace

aquarium, then using ::blowfish within is contextually meaningful. Likewise, when

adding metadata to structures, you should consider using qualified keywords as keys

and directives if their intention is domain-oriented. Observe the following code:

Download from Wow! eBook <www.wowebook.com>

70

CHAPTER 4 On scalars

(continued)

(defn do-blowfish [directive]

(case directive

:aquarium/blowfish (println "feed the fish")

:crypto/blowfish

(println "encode the message")

:blowfish

(println "not sure what to do")))

(ns crypto)

(user/do-blowfish :blowfish)

; not sure what to do

(user/do-blowfish ::blowfish)

; encode the message

(ns aquarium)

(user/do-blowfish :blowfish)

; not sure what to do

(user/do-blowfish ::blowfish)

; feed the fish

When switching to different namespaces using ns, you can use the namespace-qual-

ified keyword syntax to ensure that the correct domain-specific code path is executed.

Namespace qualification is especially important when you’re creating ad-hoc hierar-

chies and defining multimethods, both discussed in section 9.2.

4.4

Symbolic resolution

In the previous section, we covered the differences between symbols and keywords.

Whereas keywords were fairly straightforward, symbols abide by a slightly more com-

plicated system for lookup resolution.

Symbols in Clojure are roughly analogous to identifiers in many other languages—

words that refer to other things. In a nutshell, symbols are primarily used to provide a

name for a given value. But in Clojure, symbols can also be referred to directly, by

using the symbol or quote function or the ' special operator. Symbols tend to be dis-

crete entities from one lexical contour to another, and often even within a single con-

tour. Unlike keywords, symbols aren’t unique based solely on name alone, as you can

see in the following:

(identical? 'goat 'goat)

;=> false

The reason identical? returns false in this example is because each goat symbol is a

discrete object that only happens to share a name and therefore a symbolic represen-

tation. But that name is the basis for symbol equality:

(= 'goat 'goat)

;=> true

(name 'goat)

"goat"

Download from Wow! eBook <www.wowebook.com>

Symbolic resolution

71

The identical? function in Clojure only ever returns true when the symbols are in

fact the same object:

(let [x 'goat y x] (identical? x y))

;=> true

In the preceding example, x is also a symbol, but when evaluated in the (identical?

x x) form it returns the symbol goat, which is actually being stored on the runtime

call stack. The question arises: why not make two identically named symbols the same

object? The answer lies in metadata, which we discuss next.

4.4.1

Metadata

Clojure allows the attachment of metadata to various objects, but for now we’ll focus

on attaching metadata to symbols. The with-meta function takes an object and a map

and returns another object of the same type with the metadata attached. The reason

why equally named symbols are often not the same instance is because each can have

its own unique metadata:

(let [x (with-meta 'goat {:ornery true})

y (with-meta 'goat {:ornery false})]

[(= x y)

(identical? x y)

(meta x)

(meta y)])

;=> [true false {:ornery true} {:ornery false}]

The two locals x and y both hold an equal symbol 'goat, but they’re different

instances, each containing separate metadata maps obtained with the meta function.

The implications of this are that symbol equality isn’t dependent on metadata or iden-

tity. This equality semantic isn’t limited to symbols, but is pervasive in Clojure, as we’ll

demonstrate throughout this book. You’ll find that keywords can’t hold metadata6

because any equally named keyword is the same object.

4.4.2

Symbols and namespaces

Like keywords, symbols don’t belong to any specific namespace. Take, for example,

the following code:

(ns where-is)

(def a-symbol 'where-am-i)

a-symbol

;=> where-am-i

(resolve 'a-symbol)

;=> #'where-is/a-symbol

à-symbol

;=> where-is/a-symbol

6 Java class instances, including strings, can’t hold metadata either.

Download from Wow! eBook <www.wowebook.com>

72

CHAPTER 4 On scalars

The initial evaluation of a-symbol shows the expected value where-am-i. But attempt-

ing to resolve the symbol using resolve and using syntax-quote returns what looks

like (as printed at the REPL) a namespace-qualified symbol. This is because a symbol’s

qualification is a characteristic of evaluation and not inherent in the symbol at all.

This also applies to symbols qualified with class names. This evaluation behavior will

prove beneficial when we discuss macros in chapter 8, but for now we can summarize

the overarching idea known as Lisp-1 (Gabriel 2001).

4.4.3

Lisp-1

Clojure is what’s known as a Lisp-1, which in simple terms means it uses the same

name resolution for function and value bindings. In a Lisp-2 programming language

like Common Lisp, these name resolutions are performed differently depending on

the context of the symbol, be it in a function call position or a function argument

position. There are many arguments for and against both Lisp-1 and Lisp-2, but

against Lisp-1 one downside bears consideration. Because the same name-resolution

scheme is used for functions and their arguments, there’s a real possibility of

shadowing existing functions with other locals or Vars. Name shadowing isn’t neces-

sarily non-idiomatic if done thoughtfully, but if done accidentally it can lead to some

unexpected and obscure errors. You should take care when naming locals and defin-

ing new functions so that name-shadowing complications can be avoided.

Though name-shadowing errors tend to be rare, the benefit in a simplified mecha-

nism for calling and passing first-class functions far outweighs the negative. Clojure’s

adoption of a Lisp-1 resolution scheme makes for cleaner implementations and there-

fore highlights the solution rather than muddying the waters with the nuances of sym-

bolic lookup. For example, the best function highlights this perfectly in the way that

it takes the greater-than function > and calls it within its body as f:

(defn best [f xs]

(reduce #(if (f % %2) % %2) xs))

(best > [1 3 4 2 7 5 3])

;=> 7

A similar function body using a Lisp-2 language would require the intervention of

another function (in this case funcall) responsible for invoking the function explic-

itly. Likewise, passing any function would require the use of a qualifying tag marking it

as a function object, as seen here:

(defun best (f xs)

(reduce #'(lambda (l r)

(if (funcall f l r) l r))

xs))

(best #'> '(1 3 4 2 7 5 3))

;=> 7

This section isn’t intended to champion the cause of Lisp-1 over Lisp-2, only to high-

light the differences between the two. Many of the design decisions in Clojure provide

succinctness in implementation, and Lisp-1 is no exception. The preference for Lisp-1

Download from Wow! eBook <www.wowebook.com>

Regular expressions—the second problem

73

versus Lisp-2 typically boils down to matters of style and taste; by all practical mea-

sures, they’re equivalent.

Having covered the two symbolic scalar types, we now move into a type that you’re

(for better or worse) likely familiar with: the regular expression.

4.5

Regular expressions—the second problem

Some people, when confronted with a problem, think “I know, I’ll use regular expres-

sions.” Now they have two problems.

—Jamie Zawinski

Regular expressions are a powerful and compact way to find specific patterns in text

strings. Though we sympathize with Zawinski’s attitude and appreciate his wit, some-

times regular expressions are a useful tool to have on hand. Although the full capabil-

ities of regular expressions (or regexes) are well beyond the scope of this section

(Friedl 1997), we’ll look at some of the ways Clojure leverages Java’s regex capabilities.

Java’s regular expression engine is reasonably powerful, supporting Unicode and

features such as reluctant quantifiers and “look-around” clauses. Clojure doesn’t try to

reinvent the wheel and instead provides special syntax for literal Java regex patterns

plus a few functions to help Java’s regex capabilities fit better with the rest of Clojure.

4.5.1

Syntax

A literal regular expression in Clojure looks like this:

#"an example pattern"

This produces7 a compiled regex object that can be used either directly with Java

interop method calls or with any of the Clojure regex functions described later:

(class #"example")

;=> java.util.regex.Pattern

Though the pattern is surrounded with double quotes like string literals, the way

things are escaped within the quotes isn’t the same. This difference is easiest to see in

patterns that use backslash-delimited character classes. When compiled as a regex, a

string "\\d" will match a single digit and is identical to a literal regex without the dou-

ble backslash. Note that Clojure will even print the pattern back out using the literal

syntax:

(java.util.regex.Pattern/compile "\\d")

;=> #"\d"

In short, the only rules you need to know for embedding unusual literal characters or

predefined character classes are listed in the javadoc for Pattern.8

7

Literal regex patterns are compiled to java.util.regex.Pattern instances at read-time. This means, for example,

if you use a literal regex in a loop, it’s not recompiled each time through the loop, but just once when the

surrounding code is compiled.

8

See the online reference at http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html.

Download from Wow! eBook <www.wowebook.com>

74

CHAPTER 4 On scalars

Regular expressions accept option flags, shown in table 4.1, that can make a pat-

tern case-insensitive or enable multiline mode, and Clojure’s regex literals starting

with (?<flag>) set the mode for the rest of the pattern.

Table 4.1 Regex flags: these are the flags that can be used within Clojure regular expression patterns,

their long name, and a description of what they do. See Java's documentation for the java.util.

regex.Pattern class for more details.

Flag

Flag name

Description

d

UNIX_LINES

., ^, and $ match only the Unix line terminator '\n'.

i

CASE_INSENSITIVE

ASCII characters are matched without regard to upper or lower case.

x

COMMENTS

Whitespace and comments in the pattern are ignored.

m

MULTILINE

^ and $ match near line terminators instead of only at the beginning or

end of the entire input string.

s

DOTALL

. matches any character including the line terminator.

u

UNICODE_CASE

Causes the i flag to use Unicode case insensitivity instead of ASCII.

For example, the pattern #"(?i)yo" would match the strings “yo”, “yO”, “Yo”, and “YO”.

4.5.2

Functions

Java’s regex Pattern object has several methods that can be used directly, but only

split is used regularly to split a string into an array9 of Strings, breaking the original

where the pattern matches:

(seq (.split #"," "one,two,three"))

;=> ("one" "two" "three")

The re-seq function is Clojure’s regex workhorse. It returns a lazy seq of all matches

in a string, which means it can be used to efficiently test whether a string matches at

all or to find all matches in a string or a mapped file:

(re-seq #"\w+" "one-two/three")

;=> ("one" "two" "three")

The preceding regular expression has no capturing groups, so each match in the

returned seq is simply a string. A capturing group in the regex causes each returned

item to be a vector:

(re-seq #"\w*(\w)" "one-two/three")

;=> (["one" "e"] ["two" "o"] ["three" "e"])

9 Java arrays don’t print very pleasantly at the Clojure REPL, so we used seq in this example so you can see the

Strings inside.

Download from Wow! eBook <www.wowebook.com>

Summary

75

So where .split returns the text between regex matches, re-seq returns the matches

themselves.10 Now that we’ve looked at some nice functions you can use, we’ll talk

about one object you shouldn’t.

4.5.3

Beware of mutable matchers

Java’s regular expression engine includes a Matcher object that mutates in a non-

thread-safe way as it walks through a string finding matches. This object is exposed by

Clojure via the re-matcher function and can be used as an argument to re-groups

and the single-parameter form of re-find. We highly recommend avoiding all of

these unless you’re certain you know what you’re doing. These dangerous functions

are used internally by the implementations of some of the recommended functions

described earlier, but in each case they’re careful to disallow access to the Matcher

object they use. Use Matchers at your own risk, or better yet don’t use them directly11

at all.

4.6

Summary

Clojure’s scalar types generally work as expected, but its numerical types have a poten-

tial for frustration in certain situations. Though you may rarely encounter issues with

numerical precision, keeping in mind the circumstances under which they occur

might prove useful in the future. Given its inherent arbitrary-precision big decimal

and rational numerics, Clojure provides the tools for perfectly accurate calculations.

Keywords in Clojure serve many purposes and are ubiquitous in idiomatic code. When

dealing directly with symbols, Clojure’s nature as a Lisp-1 defines the nature of how

symbolic resolution occurs. Finally, Clojure provides regular expressions as first-class

data types, and their usage is encouraged where appropriate.

As you might’ve speculated, this chapter was nice and short due to the relative sim-

plicity of scalar types. In the following chapter, we’ll step it up a notch or 10 when cov-

ering Clojure’s composite data types. Though scalars are interesting and deeper than

expected, the next chapter will start you on your way to understanding Clojure’s true

goal: providing a sane approach to application state.

10 If you want both at the same time, you may want to look at the partition function in the clojure-contrib

library, found in the clojure.contrib.string namespace.

11 The clojure.contrib.string namespace has a bevy of functions useful for leveraging regular expres-

sions.

Download from Wow! eBook <www.wowebook.com>

Composite data types

It is better to have 100 functions

operate on one data structure than 10

functions on 10 data structures.

—Alan Perlis

This chapter covers

 Persistence, sequences, and complexity

 Vectors: creating and using them in all their varieties

 Lists: Clojure’s code form data structure

 How to use persistent queues

 Persistent sets

 Thinking in maps

 Putting it all together: finding the position of items in a

sequence

Clojure provides a rich set of composite data types and we’ll cover them all: vectors,

lists, queues, sets, and maps. In this chapter, we’ll dig into the strengths and weak-

nesses of each. We’ll spend more time on vectors and maps than on the other types,

because those two are used in a wider variety of circumstances and warrant the

extra discussion. Finally, we’ll discuss the design of a simple function to leverage

76

Download from Wow! eBook <www.wowebook.com>

Persistence, sequences, and complexity

77

many of the lessons learned in this chapter, and you’ll gain specific insight into the

preceding quote. By the way, we use the terms composite types and collections inter-

changeably, so please bear that in mind as we proceed.

Before we look at the primary collection types individually, we’ll discuss the things

they have in common. For example, you may have heard of Clojure’s sequence

abstraction —all the persistent collections use it, so we’ll examine that as well as some

algorithmic complexity concepts we’ll be referring to throughout the chapter.

5.1

Persistence, sequences, and complexity

Clojure’s composite data types have some unique properties compared to composites

in many mainstream languages. Terms such as persistent and sequence come up, and not

always in a way that makes their meaning clear. In this section we’ll define their mean-

ings carefully. We’ll also briefly examine the topic of algorithmic complexity and Big-O

notation as they apply to Clojure collections.

The term persistent is particularly problematic because it means something differ-

ent in other contexts. In the case of Clojure, we believe that a phrase immortalized by

Inigo Montoya from the novel and subsequent film The Princess Bride summarizes your