
- •Contents
- •Foreword
- •Acknowledgments
- •Preface
- •Who This Book Is For
- •What Is in This Book
- •How to Read This Book
- •Notation Conventions
- •Web Resources and Feedback
- •Downloading Sample Code
- •Getting Started
- •Why Clojure?
- •Clojure Coding Quick Start
- •Exploring Clojure Libraries
- •Introducing Lancet
- •Wrapping Up
- •Exploring Clojure
- •Forms
- •Reader Macros
- •Functions
- •Vars, Bindings, and Namespaces
- •Flow Control
- •Metadata
- •Wrapping Up
- •Working with Java
- •Calling Java
- •Optimizing for Performance
- •Creating and Compiling Java Classes in Clojure
- •Exception Handling
- •Adding Ant Projects and Tasks to Lancet
- •Wrapping Up
- •Unifying Data with Sequences
- •Everything Is a Sequence
- •Using the Sequence Library
- •Clojure Makes Java Seq-able
- •Adding Properties to Lancet Tasks
- •Wrapping Up
- •Functional Programming
- •Functional Programming Concepts
- •How to Be Lazy
- •Lazier Than Lazy
- •Recursion Revisited
- •Wrapping Up
- •Concurrency
- •The Problem with Locks
- •Refs and Software Transactional Memory
- •Use Atoms for Uncoordinated, Synchronous Updates
- •Use Agents for Asynchronous Updates
- •Managing Per-Thread State with Vars
- •A Clojure Snake
- •Making Lancet Targets Run Only Once
- •Wrapping Up
- •Macros
- •When to Use Macros
- •Writing a Control Flow Macro
- •Making Macros Simpler
- •Taxonomy of Macros
- •Making a Lancet DSL
- •Wrapping Up
- •Multimethods
- •Living Without Multimethods
- •Moving Beyond Simple Dispatch
- •Creating Ad Hoc Taxonomies
- •When Should I Use Multimethods?
- •Adding Type Coercions to Lancet
- •Wrapping Up
- •Clojure in the Wild
- •Automating Tests
- •Data Access
- •Web Development
- •Farewell
- •Editor Support
- •Bibliography
- •Index
- •Symbols

CLOJURE CODING QUICK STAR T |
30 |
that in the following code the Clojure version has both fewer dots and fewer parentheses than the Java version:
// Java "hello".getClass().getProtectionDomain().getCodeSource()
; Clojure
(.. "hello" getClass getProtectionDomain getCodeSource)
Clojure provides simple functions for implementing Java interfaces and subclassing Java classes. Also, Clojure functions all implement Callable and Runnable. This makes it trivial to pass the following anonymous function to the constructor for a Java Thread.
(.start (new Thread (fn [] (println "Hello" (Thread/currentThread))))) | Hello #<Thread Thread[Thread-0,5,main]>
The #<...> is Clojure’s way of printing a Java instance. Thread is the class name of the instance, and Thread[Thread-0,5,main] is the instance’s toString representation.
(Note that in the preceding example the new thread will run to completion, but its output may interleave in some strange way with the REPL prompt. This is not a problem with Clojure but simply the result of having more than one thread writing to an output stream.)
Because the Java invocation syntax in Clojure is clean and simple, it is idiomatic to use Java directly, rather than to hide Java behind Lispy wrappers.
Now that you have seen a few of the reasons to use Clojure, it is time to start writing some code.
1.2 Clojure Coding Quick Start
To run Clojure, you need two things:
•A Java runtime. Download4 and install Java version 5 or greater. Java version 6 has significant performance improvements and better exception reporting, so prefer this if possible.
•Clojure itself. The book’s sample code includes a version of Clojure that has been tested to work with all of the book’s examples. While
4.http://java.sun.com/javase/downloads/index.jsp
Prepared exclusively for WG Custom Motorcycles
Report erratum
this copy is (P1.0 printing, May 2009)

CLOJURE CODING QUICK STAR T |
31 |
you are working through the book, use the version of Clojure bundled with the book’s sample code at lib/clojure.jar. After you read the book, you can follow the instructions in the sidebar on the next page to build an up-to-the-minute version of Clojure.
Instructions for downloading the sample code are on page 20. Once you have downloaded the sample code, you can test your install by navigating to the directory where you placed the sample code and running a Clojure read-eval-print loop (REPL). The sample code includes REPL launch scripts that load Clojure, plus several other libraries that we will need later in the book.
On *nix/Mac the script is repl.sh:
cd /wherever/you/put/the/samples bin/repl.sh
On Windows it is repl.bat:
cd \wherever\you\put\the\samples bin\repl.bat
Another alternative for Windows users is to install Cygwin5 and then follow the *nix instructions throughout the book.
When you run the appropriate REPL launch script, the REPL should prompt you with user=>:
Clojure user=>
All scripts in the book should be launched from a console in the root directory of the sample code. Do not navigate into the bin directory, and do not click the scripts from a Windows environment.
In addition to Clojure, many of the samples in the book depend on the clojure-contrib library.6 A few examples also require various Java JAR files. You do not have to worry about any of this, because the sample code includes all these files and the REPL launch scripts place them on the classpath.
Now you are ready for “Hello World.”
5.http://www.cygwin.com
6.http://code.google.com/p/clojure-contrib
Prepared exclusively for WG Custom Motorcycles
Report erratum
this copy is (P1.0 printing, May 2009)

CLOJURE CODING QUICK STAR T |
32 |
Building Clojure Yourself
Because the sample code for the book includes clojure.jar, you do not need to download anything else to get started. However, you may want to build Clojure or clojure-contrib from source to get access to newer features and bug fixes. Here’s how:
For Clojure:
svn co http://clojure.googlecode.com/svn/trunk/ clojure cd clojure
ant
For clojure-contrib:
svn co http://clojure-contrib.googlecode.com/svn/trunk/ clojure-contrib
cd clojure-contrib ant
The sample code is regularly updated to match the current development head of Clojure and clojure-contrib. Check the README file in the sample code to see the revision numbers that the samples were most recently tested with.
Warning: The SourceForge projects for Clojure and clojurecontrib are deprecated and should be ignored.
Using the REPL
To see how to use the REPL, let’s create a few variants of “Hello World.” First, type (println "hello world") at the REPL prompt:
user=> (println "hello world") | hello world
-> nil
The second line, hello world, is the console output you requested. This third line, nil, is the return value of the call to println.
Next, encapsulate your “Hello World” into a function that can address a person by name:
user=> (defn hello [name] (str "Hello, " name))
#'user/hello
Let’s break this down:
•defn defines a function.
•hello is the function name.
Prepared exclusively for WG Custom Motorcycles
Report erratum
this copy is (P1.0 printing, May 2009)

CLOJURE CODING QUICK STAR T |
33 |
•hello takes one argument, name.
•str is a function call that concatenates an arbitrary list of arguments into a string.
•defn, hello, name, and str are all symbols, which are names that refer to things. Legal symbols are defined in Section 2.1, Symbols, on page 49.
Look at the return value, #’user/hello. The prefix #’ indicates that the function was stored in a Clojure var, and user is the namespace of the function. (The user namespace is the REPL default, like the default package in Java.) You do not need to worry about vars and namespaces yet; they are covered in Section 2.4, Vars, Bindings, and Namespaces, on page 60.
Now you can call hello, passing in your name:
user=> (hello "Stu")
Hello, Stu
If you get your REPL into a state that confuses you, the simplest fix is to kill the REPL with Ctrl + C on Windows or Ctrl + D on *nix and then start another one.
Special Variables
The REPL includes several useful special variables. When you are working in the REPL, the results of evaluating the three most recent expressions are stored in the special variables *1, *2, and *3, respectively. This makes it easy to work iteratively. Say hello to a few different names:
user=> (hello "Stu")
"Hello, Stu"
user=> (hello "Clojure")
"Hello, Clojure"
Now, you can use the special variables to combine the results of your recent work:
(str *1 " and " *2)
"Hello, Clojure and Hello, Stu"
If you make a mistake in the REPL, you will see a Java exception. The details are often omitted for brevity. For example, dividing by zero is a no-no:
user=> (/ 1 0)
java.lang.ArithmeticException: Divide by zero
Prepared exclusively for WG Custom Motorcycles
Report erratum
this copy is (P1.0 printing, May 2009)

CLOJURE CODING QUICK STAR T |
34 |
Here the problem is obvious, but sometimes the problem is more subtle and you want the detailed stack trace. The *e special variable holds the last exception. Because Clojure exceptions are Java exceptions, you can call Java methods such as printStackTrace( ):
user=> (.printStackTrace *e)
java.lang.ArithmeticException: Divide by zero
| |
at |
clojure.lang.Compiler.eval(Compiler.java:4094) |
| |
at |
clojure.lang.Repl.main(Repl.java:87) |
| Caused by: java.lang.ArithmeticException: Divide by zero
| |
at |
clojure.lang.Numbers.divide(Numbers.java:142) |
| |
at |
user.eval__2677.invoke(Unknown Source) |
| |
at |
clojure.lang.Compiler.eval(Compiler.java:4083) |
| ... |
1 more |
Java interop is covered in Chapter 3, Working with Java, on page 79.
If you have a block of code that is too large to conveniently type at the REPL, save the code into a file, and then load that file from the REPL. You can use an absolute path or a path relative to where you launched the REPL:
; save some work in temp.clj, and then ...
user=> (load-file "temp.clj")
The REPL is a terrific environment for trying ideas and getting immediate feedback. For best results, keep a REPL open at all times while reading this book.
Adding Shared State
The hello function of the previous section is pure; that is, it has no side effects. Pure functions are easy to develop, test, and understand, and you should prefer them for many tasks.
That said, most programs have some shared state and will use impure functions to manage that shared state. Let’s extend hello to keep track of past visitors and offer a different greeting to people it has met before. First, you will need something to track the visitors. A set will do the trick:
#{}
#{}
The #{} is a literal for an empty set. Next, you will need conj:
(conj coll item)
Prepared exclusively for WG Custom Motorcycles
Report erratum
this copy is (P1.0 printing, May 2009)

CLOJURE CODING QUICK STAR T |
35 |
conj is short for conjoin, and it builds a new collection with an item added. conj an element onto a set to see that a new set is created:
(conj #{} "Stu")
#{"Stu"}
Now that you can build new sets, you need some way to keep track of the current set of visitors. Clojure provides references (refs) for this purpose:
(ref initial-state)
To name your reference, you can use def:
(def symbol initial-value?)
def is like defn but more general. A def can define functions or data. Use ref to create a reference, and use def to bind this reference to the name visitors:
(def visitors (ref #{}))
#'user/visitors
In order to update a reference, you must use a function such as alter:
(alter r update-fn & args)
alter applies an update-fn to reference r, with optional args if necessary. Try to alter a visitor into visitors, using conj as the update function:
(alter visitors conj "Stu")
java.lang.IllegalStateException: No transaction running
As you can see, Clojure protects references. References must be updated in a transaction so that Clojure can do the hard work of dealing with multiple concurrent users of visitors:
To create a transaction, use dosync:
(dosync & exprs)
Use dosync to add a visitor within a transaction:
(dosync (alter visitors conj "Stu"))
#{"Stu"}
alter is one of several functions that can update a ref. Choosing the right update function requires care and is discussed in Section 6.2, Refs and Software Transactional Memory, on page 179.
Prepared exclusively for WG Custom Motorcycles
Report erratum
this copy is (P1.0 printing, May 2009)

CLOJURE CODING QUICK STAR T |
36 |
At any time, you can peek inside the ref with deref or with the shorter
@:
(deref visitors)
#{"Stu"}
@visitors
#{"Stu"}
Now you are ready to build the new, more elaborate version of hello:
Download examples/introduction.clj
Line 1 (defn hello
-"Writes hello message to *out*. Calls you by username.
-Knows if you have been here before."
-[username]
5 (dosync
-(let [past-visitor (@visitors username)]
-(if past-visitor
-(str "Welcome back, " username)
-(do
10 |
(alter visitors conj username) |
-(str "Hello, " username))))))
On line 6, @visitors returns the current value of the visitors reference. Sets are functions of their members, so (@visitors username) checks to see whether username is a member of the current value of visitors. The let then binds the result of this check to the name past-visitor.
On line 10, alter updates the visitors to include the name username.
Lines 8 and 11 return different strings based on whether the user was a visitor in the past.
You can verify that new visitors get one message the first time around:
(hello "Rich")
"Hello, Rich"
...and that they get a different message when they return again later:
(hello "Rich")
"Welcome back, Rich"
The use of references and transactions in the previous example offers a great benefit: the hello function is safe for multiple threads and processors. And although they may be retried, calls to dosync will not deadlock. Clojure transactions are described in more detail in Chapter 6,
Concurrency, on page 177.
Prepared exclusively for WG Custom Motorcycles
Report erratum
this copy is (P1.0 printing, May 2009)