The Joy of Clojure
MICHAEL FOGUS
CHRIS HOUSER
MANNING
Greenwich
(74° w. long.)
www.it-ebooks.info
For online information and ordering of this and other Manning books, please visit
www.manning.com. The publisher offers discounts on this book when ordered in quantity.
For more information, please contact
Special Sales Department
Manning Publications Co.
180 Broad St.
Suite 1323
Stamford, CT 06901
Email:
©2011 by Manning Publications Co. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in
any form or by means electronic, mechanical, photocopying, or otherwise, without prior written
permission of the publisher.
Many of the designations used by manufacturers and sellers to distinguish their products are
claimed as trademarks. Where those designations appear in the book, and Manning
Publications was aware of a trademark claim, the designations have been printed in initial caps
or all caps.
Recognizing the importance of preserving what has been written, it is Manning’s policy to have
the books we publish printed on acid-free paper, and we exert our best efforts to that end.
Recognizing also our responsibility to conserve the resources of our planet, Manning books
are printed on paper that is at least 15 percent recycled and processed without the use of
elemental chlorine.
Manning Publications Co. Development editor: Susan Harkins
180 Broad St. Copyeditor: Benjamin Berg
Suite 1323 Typesetter: Dottie Marsico
Stamford, CT 06901 Cover designer: Marija Tudor
ISBN 978-1-935182-64-1
Printed in the United States of America
1 2 3 4 5 6 7 8 9 10 – MAL – 16 15 14 13 12 11
www.it-ebooks.info
vii
brief contents
PART 1 FOUNDATIONS 1
1
■
Clojure philosophy 3
2
■
Drinking from the Clojure firehose 20
3
■
Dipping our toes in the pool 43
PART 2 DATA TYPES . 59
4
■
On scalars 61
5
■
Composite data types 76
PART 3 FUNCTIONAL PROGRAMMING 105
6
■
Being lazy and set in your ways 107
7
■
Functional programming 125
PART 4 LARGE-SCALE DESIGN 155
8
■
Macros 157
9
■
Combining data and code 177
10
■
Java.next 207
11
■
Mutation 234
PART 5 TANGENTIAL CONSIDERATIONS 275
12
■
Performance 277
13
■
Clojure changes the way you think 292
www.it-ebooks.info
ix
contents
foreword xvii
preface xix
acknowledgments xxi
about this book xxiii
PART 1 FOUNDATIONS 1
1
Clojure philosophy 3
1.1 The Clojure way 4
Simplicity 4
■
Freedom to focus 5
■
Empowerment 5
Clarity 6
■
Consistency 7
1.2 Why a(nother) Lisp? 8
Beauty 9
■
Extreme flexibility 9
■
Code is data 11
1.3 Functional programming 12
A workable definition of functional programming 12
The implications of functional programming 12
1.4 Why Clojure isn’t especially object-oriented 13
Defining terms 13
■
Imperative “baked in” 14
■
Most of what
OOP gives you, Clojure provides 15
1.5 Summary 19
www.it-ebooks.info
CONTENTSx
2
Drinking from the Clojure firehose 20
2.1 Scalars 21
Numbers 21
■
Integers 22
■
Floating-point numbers 22
Rationals 22
■
Symbols 23
■
Keywords 23
■
Strings 23
Characters 23
2.2 Putting things together: collections 24
Lists 24
■
Vectors 24
■
Maps 25
■
Sets 25
2.3 Making things happen: functions 25
Calling functions 25
■
Defining functions 26
■
Simplifying
function definitions with def and defn 27
■
In-place functions
with #() 28
2.4 Vars 28
Declaring bindings using def 28
2.5 Locals, loops, and blocks 29
Blocks 29
■
Locals 29
■
Loops 30
2.6 Preventing things from happening: quoting 32
Evaluation 32
■
Quoting 33
■
Unquote 34
Unquote-splicing 35
■
Auto-gensym 36
2.7 Leveraging Java via interop 36
Accessing static class members 36
■
Creating Java class
instances 36
■
Accessing Java instance members with the .
operator 37
■
Setting Java instance properties 37
The macro 37
■
The doto macro 38
■
Defining classes 38
2.8 Exceptional circumstances 38
A little pitch and catch 38
2.9 Namespaces 39
Creating namespaces using ns 39
■
Loading other namespaces
with :require 40
■
Loading and creating mappings with :use 40
Creating mappings with :refer 41
■
Loading Java classes with
:import 42
2.10 Summary 42
3
Dipping our toes in the pool 43
3.1 Truthiness 44
What’s truth? 44
■
Don’t create Boolean objects 44
nil versus false 45
3.2 Nil pun with care 45
www.it-ebooks.info
CONTENTS xi
3.3 Destructuring 47
Your assignment, should you choose to accept it 47
Destructuring with a vector 47
■
Destructuring with a map 49
Destructuring in function parameters 50
■
Destructuring versus
accessor methods 50
3.4 Using the REPL to experiment 51
Experimenting with seqs 51
■
Experimenting with graphics 52
Putting it all together 54
■
When things go wrong 54
Just for fun 56
3.5 Summary 56
PART 2 DATA TYPES 59
4
On scalars 61
4.1 Understanding precision 62
Truncation 62
■
Promotion 63
■
Overflow 64
Underflow 64
■
Rounding errors 64
4.2 Trying to be rational 65
Why be rational? 66
■
How to be rational 66
■
Caveats of
rationality 67
4.3 When to use keywords 68
How are keywords different from symbols? 68
■
Qualifying your
keywords 69
4.4 Symbolic resolution 70
Metadata 71
■
Symbols and namespaces 71
■
Lisp-1 72
4.5 Regular expressions—the second problem 73
Syntax 73
■
Functions 74
■
Beware of mutable matchers 75
4.6 Summary 75
5
Composite data types 76
5.1 Persistence, sequences, and complexity 77
“You keep using that word. I do not think it means what you think it
means.” 77
■
Sequence terms and what they mean 78
Big-O 81
5.2 Vectors: creating and using them in all their varieties 82
Building vectors 82
■
Large vectors 83
■
Vectors as stacks 86
Using vectors instead of reverse 87
■
Subvectors 88
■
Vectors as
MapEntries 88
■
What vectors aren’t 89
www.it-ebooks.info
CONTENTSxii
5.3 Lists: Clojure’s code form data structure 90
Lists like Lisps like 90
■
Lists as stacks 91
■
What lists
aren’t 91
5.4 How to use persistent queues 91
A queue about nothing 92
■
Putting things on 92
■
Getting
things 93
■
Taking things off 93
5.5 Persistent sets 94
Basic properties of Clojure sets 94
■
Keeping your sets in order with
sorted-set 94
■
contains? 95
■
clojure.set 96
5.6 Thinking in maps 97
Hash maps 97
■
Keeping your keys in order with sorted maps 99
Keeping your insertions in order with array maps 100
5.7 Putting it all together: finding the position of items
in a sequence 101
Implementation 101
5.8 Summary 103
PART 3 FUNCTIONAL PROGRAMMING 105
6
Being lazy and set in your ways 107
6.1 On immutability 107
Defining immutability 108
■
Being set in your ways—
immutability 109
6.2 Designing a persistent toy 110
6.3 Laziness 113
Familiar laziness with logical-and 113
■
Understanding the lazy-
seq recipe 115
■
Losing your head 117
■
Employing infinite
sequences 118
■
The delay and force macros 119
6.4 Putting it all together: a lazy quicksort 121
6.5 Summary 124
7
Functional programming 125
7.1 Functions in all their forms 126
First-class functions 126
■
Higher-order functions 129
Pure functions 131
■
Named arguments 132
■
Constraining
functions with pre- and postconditions 133
www.it-ebooks.info
CONTENTS xiii
7.2 Closures 135
7.3 Thinking recursively 141
Mundane recursion 142
■
Tail calls and recur 143
■
Don’t
forget your trampoline 146
■
Continuation-passing style 148
7.4 Putting it all together: A* pathfinding 149
The A* implementation 151
■
Notes about the A*
implementation 154
7.5 Summary 154
PART 4 LARGE-SCALE DESIGN. 155
8
Macros 157
8.1 Data is code is data 158
Syntax-quote, unquote, and splicing 160
■
Macro rules of
thumb 161
8.2 Defining control structures 161
Defining control structures without syntax-quote 162
Defining control structures using syntax-quote and unquoting 163
8.3 Macros combining forms 164
8.4 Using macros to change forms 165
8.5 Using macros to control symbolic resolution time 169
Anaphora 170
■
(Arguably) useful selective name
capturing 171
8.6 Using macros to manage resources 171
8.7 Putting it all together: macros returning functions 173
8.8 Summary 176
9
Combining data and code 177
9.1 Namespaces 178
Creating namespaces 179
■
Expose only what’s needed 180
Declarative inclusions and exclusions 182
9.2 Exploring Clojure multimethods with the Universal
Design Pattern 183
The parts 184
■
Usage 185
■
Multimethods to the rescue 185
Ad hoc hierarchies for inherited behaviors 186
■
Resolving conflict
in hierarchies 187
■
Arbitrary dispatch for true maximum
power 188
www.it-ebooks.info
CONTENTSxiv
9.3 Types, protocols, and records 189
Records 189
■
Protocols 192
■
Building from a more primitive
base with deftype 200
9.4 Putting it all together: a fluent builder for chess moves 202
Java implementation 202
■
Clojure implementation 204
9.5 Summary 206
10
Java.next 207
10.1 Generating objects on the fly with proxy 208
A simple dynamic web service 209
10.2 Clojure gen-class and GUI programming 212
Namespaces as class specifications 212
■
Exploring user interface
design and development with Clojure 215
10.3 Clojure’s relationship to Java arrays 218
Types of arrays: primitive and reference 218
■
Array mutability 220
That unfortunate naming convention 221
■
Multidimensional
arrays 222
■
Variadic method/constructor calls 222
10.4 All Clojure functions implement 222
java.util.Comparator 223
■
java.lang.Runnable 223
java.util.concurrent.Callable 224
10.5 Using Clojure data structures in Java APIs 224
java.util.List 225
■
java.lang.Comparable 225
java.util.RandomAccess 226
■
java.util.Collection 226
java.util.Set 227
10.6 definterface 227
Generating interfaces on the fly 227
10.7 Be wary of exceptions 229
A bit of background regarding exceptions 230
■
Runtime versus
compile-time exceptions 230
■
Handling exceptions 232
Custom exceptions 233
10.8 Summary 233
11
Mutation 234
11.1 Software transactional memory with multiversion
concurrency control and snapshot isolation 235
Transactions 236
■
Embedded transactions 236
■
The things
that STM makes easy 237
■
Potential downsides 238
The things that make STM unhappy 239
www.it-ebooks.info
CONTENTS xv
11.2 When to use Refs 240
Coordinated, synchronous change using alter 241
■
Commutative
change with commute 244
■
Vulgar change with ref-set 245
Fixing write-skew with ensure 245
■
Refs under stress 246
11.3 When to use Agents 247
In-process versus distributed concurrency models 248
Controlling I/O with an Agent 249
■
The difference between send
and send-off 251
■
Error handling 252
■
When not to use
Agents 254
11.4 When to use Atoms 255
Sharing across threads 255
■
Using Atoms in transactions 256
11.5 When to use locks 258
Safe mutation through locking 259
■
Using Java’s explicit
locks 260
11.6 When to use futures 261
Futures as callbacks 262
11.7 When to use promises 265
Parallel tasks with promises 265
■
Callback API to blocking
API 266
■
Deterministic deadlocks 267
11.8 Parallelism 268
pvalues 268
■
pmap 269
■
pcalls 269
11.9 Vars and dynamic binding 270
The binding macro 271
■
Creating a named Var 271
Creating anonymous Vars 272
■
Dynamic scope 273
11.10 Summary 274
PART 5 TANGENTIAL CONSIDERATIONS 275
12
Performance 277
12.1 Type hints 278
Advantages of type adornment 278
■
Type-hinting arguments
and returns 278
■
Type-hinting objects 280
12.2 Transients 280
Ephemeral garbage 280
■
Transients compare in efficiency to
mutable collections 281
12.3 Chunked sequences 282
Regaining one-at-a-time laziness 283
www.it-ebooks.info
CONTENTSxvi
12.4 Memoization 284
Re-examining memoization 285
■
A memoization protocol 285
12.5 Understanding coercion 287
First rule of coercion: don’t 288
■
Corollary: you’re probably not
doing it right 288
■
Second rule of coercion: don’t 290
Third rule of coercion: coerce a stable local 290
■
Fourth rule of
coercion: watch your sizes 290
■
Fifth rule of coercion: truncate
only as a goal 290
12.6 Summary 291
13
Clojure changes the way you think 292
13.1 DSLs 293
A ubiquitous DSL 293
■
Putting parentheses around the
specification 294
■
A note about Clojure’s approach to
DSLs 298
13.2 Testing 298
Some useful techniques 299
■
Contracts programming 301
13.3 A lack of design patterns 303
Clojure’s first-class design patterns 303
13.4 Error handling and debugging 306
Error handling 306
■
Debugging 308
13.5 Fare thee well 312
resources 313
index 319
www.it-ebooks.info
xvii
foreword
The authors of this book have taken an ambitious and aggressive approach to teach-
ing Clojure. You know how everyone loves to say they teach using the “drinking from a
fire hydrant” method? Well, at times it feels like these guys are trying to shove that fire
hydrant right up let’s just say it’s a place where you don’t normally put a fire
hydrant. This isn’t intended as a first book on programming, and it may not be an
ideal first book on Clojure either. The authors assume you’re fearless and, impor-
tantly, equipped with a search engine. You’ll
want to have Google handy as you go
through the examples. The authors blaze through many of the classics of both func-
tional programming and industry programming in a whirlwind tour of Clojure that
feels at times more like a class-five tropical storm. You’ll learn fast!
Our industry, the global programming community, is fashion-driven to a degree
that would embarrass haute couture designers from New York to Paris. We’re slaves to
fashion. Fashion dictates the programming languages people study in school, the lan-
guages employers hire for, the languages that ge
t to be in books on shelves. A naive
outsider might wonder if the quality of a language matters a little, just a teeny bit at
least, but in the real world fashion trumps all.
So nobody could be more surprised than I that a
Lisp dialect has suddenly become
fashionable again. Clojure has only been out for three years, but it’s gaining momen-
tum at a rate that we haven’t seen in a new language in decades. And it doesn’t even
have a “killer app” yet, in the way that browsers pushed JavaScript into the spotlight,
or Rails propelled Ruby. Or maybe the killer app for Clojure is the JVM itself. Every-
one’s fed up with the Java language, but understandably we don’t want to abandon
our investment in the Java Virtual Machine and its capabilities: the libraries, the con-
figuration, the monitoring, and all the other entirely valid reasons we still use it.
www.it-ebooks.info
FOREWORDxviii
For those of us using the JVM or .NET, Clojure feels like a minor miracle. It’s an
astoundingly high-quality language, sure—in fact, I’m beginning to think it’s the best
I’ve ever seen—yet somehow it has still managed to be fashionable. That’s quite a
trick. It gives me renewed hope for the overall future of productivity in our industry.
We might just dig ourselves out of this hole we’re in and get back to where every proj-
ect feels like a legacy-free startup, just like it was in the
early days of Java.
There are still open questions about Clojure’s suitability for production shops,
especially around the toolchain. That’s normal and expected for a new language. But
Clojure shows so much promise, such beautiful and practical design principles, that
everyone seems to be jumping in with both feet anyway. I certainly am. I haven’t had
this much fun with a new language since Java arrived on the scene 15 years ago. There
have been plenty of pretenders to the
JVM throne, languages that promised to take
the Java platform to unprecedented new levels. But until now, none of them had the
right mix of expressiveness, industrial strength, performance, and just plain fun.
I think maybe it’s the “fun” part that’
s helped make Clojure fashionable.
In some sense, all this was inevitable, I think. Lisp—the notion of writing your code
directly in tree form—is an idea that’s discovered time and again. People have tried all
sorts of crazy alternatives, writing code in XML or in opaque binary formats or using
cumbersome code generators. But their artificial Byzantine empires always fall into
disrepair or crush themselves into collapse while Lisp, the road that wanders through
time, remains simple, elegant, and pure. All we needed to get back on that road was a
modern approach, and Rich Hickey has given it to us in Clojure.
The Joy
of Clojure just might help make Clojure as fun for you as it is for us.
STEVE YEGGE
GOOGLE
steve-yegge.blogspot.com
www.it-ebooks.info
xix
preface
To fully appreciate Clojure, we hearken back to Paul Graham’s essay “Beating the
Averages,” an interesting look at the inner workings of his company Viaweb during
the years prior to being bought by Yahoo! Inc. in 1998. Though interesting as survey
of startup culture, the truly memorable part of the essay was the description of how
Viaweb used the programming language Lisp as an advantage over its competition.
How could a programming language more than 50 years old provide any market
advantage over Viaweb’s competitors, who were surely using modern enterprise tech-
nologies? Without repeating the exact terms of the essay
, Graham makes a compelling
case for the capability of Lisp to facilitate a more agile programming environment.
Clojure is a dialect of Lisp directly supporting concurrent software development
using functional programming techniques, and like the Lisp described in “Beating
the Averages,” provides an environment conducive to agility. Clojure fosters agility in
ways that many popular programming languages can’t. Many programming languages
are bewitched with most or all of the following:
■
Verbosity
■
Unavoidable boilerplate
■
A long thought-code-feedback loop
■
Incidental complexity
■
Difficulties in extension
■
Deficiencies in supporting crucial programming paradigms
In contrast, Clojure provides a mixture of power and practicality fostering rapid devel-
opment cycles. But the benefits of Clojure don’t stop with its agile nature—as the
www.it-ebooks.info
PREFACExx
clarion call declares, “Multicore is the new hot topic” (Mache Creeger in ACM Queue,
vol. 3, no. 7).
Though the idea of multicore processors isn’t in itself new, its importance is
becoming increasingly focused. Until recently, you could avoid concurrent and paral-
lel programming techniques and instead ride the ever-quickening processor wave to
better performance. Well, that ride is slowing to a stop, and Clojure is here to help.
Clojure provides a unique mix of functional programming and host symbiosis —an
embrace of and direct support for its host platform, in this case the Java Virtual
Machine. Additionally, the simplification and often elimination of the complexities
involved in coordinated state change have positioned Clojure as an important lan-
guage moving forward. Al
l software developers must eventually address these prob-
lems as a matter of course, and the study, understanding, and eventual utilization of
Clojure is an essential path toward conquering them. From topics such as software
transactional memory to laziness to immutability, this book will guide you on your way
to understanding the “why” of Clojure, in addition to the “how.”
We’ll be your guides into a thoughtful und
erstanding of the joyfulness in Clojure,
for we believe its art is prelude to a new age of software development.
www.it-ebooks.info
xxi
acknowledgments
The authors would like to jointly thank Rich Hickey, the creator of Clojure, for his
thoughtful creation, furthering the state of the art in language design. Without his
hard work, devotion, and vision, this book would never have been.
We’d also like to thank the brilliant members of the young Clojure community,
including but not limited to: Stuart Halloway, David Edgar Liebke, Christophe Grand,
Chas Emerick, Meikel Brandmeyer, Brian Carper, Bradford Cross, Sean Devlin, Tom
Faulhaber, Stephen Gilardi, Phil Hagelberg, Konrad Hinsen, George Jahad, David
Miller, David Nolen, Laurent Petit, and Stuart Sierra. Finally, we’d like to thank a few
early adopters who took the time to provide thoughtful feedback, including Jürgen
Hötzel, Robert “Uncle Bob” Martin, Grant Michaels, Mangala Sadhu Sangeet Singh
Khalsa, and Sam Aaron. And finally, we would like to thank Steve Yegge for agreeing
to write the foreword and for inspiring us over the years.
Manning sent out the manuscript for peer review at different stages of its develop-
ment and we would like to thank the following reviewers for their invaluable feed-
back: Art Gittleman, Stuart Caborn, Jeff Sapp, Josh Heyer, Dave Pawson, Andrew
Oswald, Federico Tomassetti, Matt Revelle, Rob Friesel, David Liebke, Pratik Patel,
Phil Hagelberg, Rich Hickey, Andy Dingley, Baishampayan Ghose, Chas Emerick,
John D’Emic, and Philipp K. Janert.
Thanks also to the team at Manning for their guidance and support, starting with
publisher Marjan Bace, associate publisher Michael Stephens, our development edi-
tor Susan Harkins, and the production team of Nicholas Chase, Benjamin Berg, Katie
Tennant, Dottie Marsico, and Mary Piergies. And again to Christophe Grand for a
final technical review of the mansucript during production.
www.it-ebooks.info
ACKNOWLEDGMENTSxxii
FOGUS
I’d like to thank my beautiful wife Yuki for her unwavering patience during the writing
of this book. Without her I would’ve never made it through. I also owe a great debt to
Chris Houser, my coauthor and friend, for teaching me more about Clojure than I
ever would’ve thought possible. I’d also like to thank Dr. Larry Albright for introduc-
ing me to Lisp and the late Dr. Russel E. Kacher for inspiring in me a passion for
learning, curiosity, and reflection. Additionally, I’d like to thank the organizers of the
National Capital Area Clojure Users Group—Matthew Courtney, Russ Olsen, and
Gray Herter—for providing a place for others in the DC area to discover Clojure.
Finally, I’d like to thank my boys Keita and Shota for teaching me the true meaning of
love and that it’s not always about me.
CHOUSER
My most grateful thanks go to God, the source of all good things. To my parents,
thanks for your love and support—your spirit of exploration launched me on a life of
wonderful adventure. To my brother Bill, thanks for my earliest introduction to com-
puters and the joys and challenges of program
ming. To my wife Heather, thanks for
your constant encouragement from the very first moments of this book project to the
last. To my friend and coauthor Michael Fogus, thanks for the brilliant inspiration and
stunning breadth of knowledge you’ve brought to these pages.
www.it-ebooks.info
xxiii
about this book
Why learn Clojure?
The only difference between Shakespeare and you was the size of his idiom list—not
the size of his vocabulary.
—Alan Perlis
When this book was conceived, our first instinct was to create a comprehensive com-
parison between Clojure and its host language, Java. After further reflection, we
reached the conclusion that such an approach would be disingenuous at best, and
disastrous at worst. Granted, some points of comparison can’t be avoided, but Java is
very different from Clojure and to try and distort one to explain the other would
respect neither. Therefore, we decided that a better approach would be to focus on
“The Clojure Way” of writing code.
When we become familiar with a programming language, the idioms and con-
structs of that language serve to define the way we think about and solve program-
ming tasks. It’s therefore natural that when faced with an entirely new language, we
find comfort in mentally mapping the new language onto the familiar old. But we
plead with you to leave all of your baggage behind; be you from Java, Lisp, Scheme,
C#, or Befunge, we ask you to bear in mind that Clojure is its own language and begs
an adherence to its own set of idioms. You’ll discover concepts that you can connect
between Clojure and languages you already know, but don’t assume that similar things
are entirely the same.
We’ll work hard to guide you through the features and semantics of Clojure to
help you build the mental model needed to use the language effectively. Most of the
samples in this book are designed to be run in Clojure’s interactive programming
www.it-ebooks.info
ABOUT THIS BOOKxxiv
environment, commonly known as the Read-Eval-Print Loop, or REPL, an extremely
powerful environment for experimentation and rapid prototyping.
By the time you’re done with this book, the Clojure way of thinking about and solv-
ing problems will be another comfortable tool in your toolbox. If we succeed, then
not only will you be a better Clojure programmer, but you’ll also start seeing your pro-
gramming language of choice—be it Java, C#, Python, Ruby, J, or Haskell—in an
entirely different light. This reassessment of topics that we often take for granted is
essential for personal growth.
Who should read this book?
Paths are made by walking.
—Franz Kafka
This book isn’t a beginner’s guide to Clojure. We start fast and don’t devote much
space to establishing a running Clojure environment, although we do provide some
guidance on page xxix. Additionally, this isn’t a book about Clojure’s implementation
details, but instead one about its semantical details. This is also not a “cookbook” for
Clojure, but instead a thorough investigation into the ingredients that Clojure pro-
vides for creating beautiful software. Often we’l
l explain how these ingredients mix
and why they make a great match, but you won’t find complete recipes for systems.
Our examples directly address the discussion at hand and at times leave exposed wir-
ing for you to extend and thus further your own know
ledge. It wouldn’t serve us, you,
or Clojure to try to awkwardly mold a comprehensive lesson into the guise of a book-
length project. Often, language books spend valuable time halfheartedly explaining
“real-world” matters totally unrelated to the language itself, and we wish to avoid this
trap. We strongly feel that if we show you the “why” of the language, then you’ll be bet-
ter prepared to take that knowledge and appl
y it to your real-world problems. In
short, if you’re looking for a book amenable to neophytes that will also show you how
to migrate Clojure into existing codebases, connect to NoSQL databases, and explore
other “real-world” topics, then we recommend the book Clojure in Action by Amit
Rathore (Manning, 2011).
Having said all of that, we do provide a sho
rt introduction to the language and feel
that for those of you willing to work hard to understand Clojure, this is indeed the
book for you. Additionally, if you already have a background in Lisp programming,
then much of the introductory material will be familiar, thus making this book ideal
for you. Though by no means perfect, Clojure has a nice combination of features that
fit together into a coherent system for solving programming problems. The way Clo-
jure encourages you to think about problems may be
different than you’re used to,
requiring a bit of work to “get.” But once you cross that threshold, you too may experi-
ence a kind of euphoria, and in this book we’ll help you get there. These are exciting
times, and Clojure is the language we hope you’ll agree is an essential tool for navigat-
ing into the future.
www.it-ebooks.info
ABOUT THIS BOOK xxv
Roadmap
We’re going to take you on a journey. Perhaps you’ve started on this journey yourself
by exploring Clojure beforehand. Perhaps you’re a seasoned Java or Lisp veteran and
are coming to Clojure for the first time. Perhaps you’re coming into this book from an
entirely different background. In any case, we’re talking to you. This is a self-styled
book for the adventurous and will require that you leave your baggage behind and
approach the enclosed topics with an open mind. In many ways, Clojure will change
the way you view programming, and in other ways it’ll obliterate your preconceived
notions. The language has a lot to say about how software should be designed and
implemented, and we’ll touch on these topics one by one throughout this book.
FOUNDATIONS
Every so often, a programming language comes along that can be considered founda-
tional. Occasionally a language is invented that shakes the foundations of the software
industry and dispels the collective preconceived notions of “good software practices.”
These foundational programming languages always introduce a novel approach to
software development, alleviating if not eliminating the difficult problems of their
time. Any list of foundational languages inevitably raises the ire of language propo-
nents who feel their preferences shouldn’t be ignor
ed. But we’re willing to take this
risk and therefore list the following programming languages in this category.
Foundational programming languages
Year Language Inventor(s) Interesting reading
1957 Fortran John Backus John Backus, “The History of Fortran I, II, and III,”
IEEE Annals of the History of Computing 20, no. 4
(1998).
1958 Lisp John McCarthy Richard P. Gabriel and Guy L. Steele Jr., “The Evolution
of Lisp” (1992), www.dreamsongs.com/Files/
HOPL2-Uncut.pdf.
1959 COBOL Design by committee Edsger Dijkstra, “EWD 498: How Do We Tell Truths
That Might Hurt?” in Selected Writings on Computing:
A Personal Perspective (New York: Springer-Verlag,
1982).
1968 Smalltalk Alan Kay Adele Goldberg, Smalltalk-80: The Language and Its
Implementation (Reading, MA: Addison-Wesley,
1983).
1972 C Dennis Ritchie Brian W. Kernighan and Dennis M. Ritchie, The C Pro-
gramming Language (Englewood Cliffs, NJ: Prentice
Hall, 1988).
1972 Prolog Alain Colmerauer Ivan Bratko, PROLOG: Programming for Artificial Intelli-
gence (New York: Addison-Wesley, 2000).
1975 Scheme Guy Steele and
Gerald Sussman
Guy Steele and Gerald Sussman, the “Lambda
Papers,” mng.bz/sU33.
www.it-ebooks.info
ABOUT THIS BOOKxxvi
Like them or not, there’s little dispute that the listed programming languages have
greatly influenced the way that software is constructed. Whether Clojure should be
included in this category remains to be seen, but Clojure does borrow heavily from
many of the foundational languages and also from other influential programming
languages to boot.
Chapter 1 starts our j
ourney and provides some of the core concepts embraced by
Clojure. These concepts should be well understood by the time you’ve finished the
chapter. Along the way, we’ll show illustrative code samples highlighting the concepts
at hand (and sometimes even pretty pictures). Much of what’s contained in chapter 1
can be deemed “The Clojure Philosophy,” so if you’ve ever wondered what inspired
and constitutes Clojure, we’ll provide that for you.
Chapter 2 provides a fast introduction to spec
ific features and syntax of Clojure.
Chapter 3 will address general Clojure programming idioms that aren’t easily cate-
gorized. From matters of truthiness and style to considerations of packaging and
nil
,
chapter 3 is a mixed bag. All of the topics are important in their own right, and to
understand them is in many ways a start to understanding a large portion of idiomatic
Clojure source code.
DATA TYPES
The discussion on scalar data types in chapter 4 will be relatively familiar to most pro-
grammers, but some important points beg our attention, arising from Clojure’s inter-
esting nature as a functional programming language hosted on the Java Virtual
Machine. Java programmers reading this book will recognize the points made concern-
ing numerical precision (section 4.1), and Lisp programmers will recognize the discus-
sion on Lisp-1 versus Lisp-2 (section 4.4). P
rogrammers will appreciate the practical
inclusion of regular expressions as first-class syntactical elements (section 4.5). Finally,
long-time Clojure programmers may find that the discussion of rationals and keywords
(sections 4.2 and 4.3, respectively) sheds new light on these seemingly innocent types.
1983 C++ Bjarne Stroustrup Bjarne Stroustrup, The Design and Evolution of C++
(Reading, MA: Addison-Wesley, 1994).
1986 Erlang Telefonaktiebolaget
L. M. Ericsson
Joe Armstrong, “A History of Erlang,” Proceedings of
the Third ACM SIGPLAN Conference on History of Pro-
gramming Languages (2007).
1987 Perl Larry Wall Larry Wall, Tom Christiansen, and Jon Orwant, Pro-
gramming Perl (Cambridge, MA: O’Reilly, 2000).
1990 Haskell Simon Peyton Jones
Miran Lipovac
ˇ
a, “Learn You a Haskell for Great
Good!” />1995 Java Sun Microsystems David Bank, “The Java Saga,” Wired 3.12 (1995).
2007 Clojure? Rich Hickey You’re reading it.
Foundational programming languages (continued)
Year Language Inventor(s) Interesting reading
www.it-ebooks.info
ABOUT THIS BOOK xxvii
Regardless of your background, chapter 4 will provide crucial information in under-
standing the nature of Clojure’s underappreciated scalar types.
Clojure’s novel persistent data structures will be covered in chapter 5; this should
be enlightening to anyone wishing to look more deeply into them. Persistent data
structures lie at the heart of Clojure’s programming philosophy and must be under-
stood to fully grasp the implications of Clojure’
s design decisions. We’ll only touch
briefly on the implementation details of these persistent structures, because they’re
less important than understanding why and how to use them.
FUNCTIONAL PROGRAMMING
Chapter 6 will deal with the nebulous notions of immutability, persistence, and lazi-
ness. We’ll explore Clojure’s use of immutability as the key element in supporting con-
current programming. We’ll likewise show how, in the presence of immutability, many
of the problems associated with coordinated state change disappear. Regarding lazi-
ness, we’ll explore the ways that Clojure leverages it to reduce the memory footprint
and speed execution times. Finally, we’ll cover the interplay between immutability and
laziness. For programmers coming from languages that allow unconstrained mutation
and strict evaluation of expressions, chapter 6 may prove to be an initially mind-
bending experience. But with this mind-bending comes enlightenment, and you’ll
likely never view your preferred programming languages in the same light.
Chapter 7 will tackle Clojure’s approach to
functional programming full-on. For
those of you coming from a functional programming background, much of the chap-
ter will be familiar, although Clojure will present its own unique blend. But like every
programming language dubbed “functional,” Clojure’s implementation will provide a
different lens by which to view your previous experience. For those of you wholly
unfamiliar with functional programming techniques, chapter 7 will likely be mind-
bending. In coming from a language that centers on object hierarchies and impera-
tive programming techni
ques, the notion of functional programming seems alien. But
we believe Clojure’s decision to base its programming model in the functional para-
digm to be the correct one, and we hope that you’ll agree.
LARGE-SCALE DESIGN
Clojure can be used as the primary language for any application scale, and the discus-
sion of macros in chapter 8 might change your ideas regarding how to develop soft-
ware. Clojure as a Lisp embraces macros, and we’ll lead you through the process of
understanding them and realizing that with great power comes great responsibility.
In chapter 9, we’ll guide you through the use of Clojure’s built-in mechanisms for
combining and relating code and data. From namespaces to multimethods to types
and protocols, we’ll explain how Clojure fosters the design and implementation of
large-scale applications.
Clojure is a symbiotic programming language, meanin
g that it’s intended to run
atop a host environment. For now, the host of choice is the Java Virtual Machine, but
the future bodes well for Clojure becoming host-agnostic. In any case, Clojure pro-
vides top-notch functions and macros for inter
acting directly with the host platform.
www.it-ebooks.info
ABOUT THIS BOOKxxviii
In chapter 10, we’ll discuss the ways that Clojure interoperates with its host, focusing
on the JVM throughout.
Clojure is built to foster the sane management of program state, which in turn
facilitates concurrent programming, as you’ll see in chapter 11. Clojure’s simple yet
powerful state model alleviates most of the headaches involved in such complicated
tasks, and we’ll show you how and why to use each. Additionally, we’ll address the mat-
ters not directly solved by Clojure, such as how to identify and reduce tho
se elements
that should be protected using Clojure’s reference types.
TANGENTIAL CONSIDERATIONS
The final part of this book will discuss topics that are equally important: the design
and development of your application viewed through the lens of the Clojure Philoso-
phy. In chapter 12, we’ll discuss ways to improve your application’s performance in
single-threaded applications. Clojure provides many mechanisms for improving per-
formance, and we’ll delve into each, including their usage and caveats where applica-
ble. And to wrap up our book, in chapter 13, we’ll address the ways that Clojure
changes the ways that you look at tangential development activities, such as the defini-
tion of your application domain language, testing, error-handling, and debugging.
Code conventions
The source code used throughout this book is formatted in a straightforward and
pragmatic fashion. Any source code listings inlined within the text, for example
(:lemonade
:fugu)
, will be formatted using a
fixed-width
font
and highlighted.
Source code snippets outlined as blocks of code will be offset from the left margin,
formatted in a
fixed-width font
, and highlighted to stand out:
(def population {::zombies 2700 ::humans 9})
(def per-capita (/ (population ::zombies) (population ::humans)))
(println per-capita "zombies for every human!")
Whenever a source code snippet indicates the result of an expression, the result will be
prefixed by the characters
;=>
. This particular sequence serves a threefold purpose:
■
It helps the result stand out from the code expressions.
■
It indicates a Clojure comment.
■
Because of this, whole code blocks can be easily copied from an EBook or PDF
version of this book and pasted into a running Clojure REPL:
(def population {::zombies 2700 ::humans 9})
(/ (population ::zombies) (population ::humans))
;=> 300
Additionally, any expected display in the REPL that’s not a returned value (such as
exceptions or printouts) will be denoted with a leading ; prior to the actual return
value:
(println population)
; {:user/zombies 2700, :user/humans 9}
;=> nil
www.it-ebooks.info
ABOUT THIS BOOK xxix
In the previous example, the map displayed as
{:user/zombies
2700,
:user/humans
9}
is the printed value, whereas
nil
denotes the returned value from the
println
function. If no return value is shown after an expression, then you can assume that it’s
either
nil
or negligible to the example at hand.
READING CLOJURE CODE When reading Clojure code, skim it when read-
ing left-to-right, paying just enough attention to note important bits of
context (
defn
,
binding
,
let
, and so on). When reading from the inside
out, pay careful attention to what each expression returns to be passed to
the next outer function. This is much easier than trying to remember the
whole outer context when reading the innermost expressions.
All code formatted as either inline or block-level is intended to be typed or pasted
e
xactly as written into Clojure source files or a
REPL. We generally won’t show the Clo-
jure prompt
user>
because it’ll cause copy/paste to fail. Finally, we’ll at times use the
ellipsis
to indicate an elided result or printout.
Code annotations accompany many of the listings, highlighting important con-
cepts. In some cases, numbered bullets link to explanations that follow the listing.
Getting Clojure
If you don’t currently have Clojure, then we recommend you retrieve the Clojure
REPL package (Cljr) created by David Edgar Liebke, located at http://joyofclo-
jure.com/cljr and installing it via the following instructions.
PREREQUISITES
■
Java version 1.6 and later
■
An Internet connection
INSTRUCTIONS
Run the following from your operating system’s console:
java -jar cljr-installer.jar
If your chosen download method appended a .zip file extension to the Cljr package,
then the following is fine:
java -jar cljr-installer.jar.zip
You’ll see output from Cljr indicating its installation and package download progress.
Once it has completed, you’ll see instructions for running Clj similar to the following:
Cljr has been successfully installed. Add $HOME/.cljr/bin to your PATH:
$ export PATH=$HOME/.cljr/bin:$PATH
Run 'cljr help' for a list of available commands.
Following the steps displayed, run Cljr.
www.it-ebooks.info
ABOUT THIS BOOKxxx
REPL
The Cljr package runs a Clojure REPL (Read/Eval/Print Loop) for version 1.2.0—the
same version corresponding to this book. When you launch the Cljr program, you’ll
see the window shown in the figure below.
The book won’t proceed under the assumption that you’r
e using Cljr but will work
regardless of your own personal REPL setup—as long as you’re running Clojure ver-
sion 1.2.
DOWNLOADING CODE EXAMPLES
Source code for all working examples in this book is available for download from the
publisher’s website at www.manning.com/TheJoyofClojure.
Author Online
Purchase of The Joy of Clojure includes free access to a private web forum run by Man-
ning Publications where you can make comments about the book, ask technical ques-
tions, and receive help from the authors and from other users. To access the forum
and subscribe to it, point your web browser to www.manning.com/TheJoyofClojure.
This page provides information on how to get on the forum once you are registered,
what kind of help is available, and the rules of conduct on the forum.
Manning’s commitment to our readers is to pro
vide a venue where a meaningful
dialogue between individual readers and between readers and the authors can take
place. It is not a commitment to any specific amount of participation on the part of
the authors, whose contribution to the
AO remains voluntary (and unpaid). We sug-
gest you try asking the authors some challenging questions lest their interest stray!
The Author Online forum and the archives of previous discussions will be accessi-
ble from the publisher’s website as long as the book is in print.
The Cljr REPL is similar to the stock Clojure REPL, but with additional convenient
features as explained at />
www.it-ebooks.info