

Michael Fogus
Chris Houser
FOREWORD BY STEVE YEGGE
M A N N I N G
The Joy of Clojure
The Joy of Clojure
MICHAEL FOGUS
CHRIS HOUSER
M A N N I N G
Greenwich
(74° w. long.)
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: orders@manning.com
©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
Download from Wow! eBook <www.wowebook.com>
The Joy of Clojure ... wherein we teach you the joys of Clojure programming.
We have written this book for you, the adventurous programmer with prior
experience in Java or functional programming languages— especially Lisp.
Our aim is to enhance your programming knowledge in general,
and your understanding of Clojure in particular, by exploring
the philosophy, motivations, and semantics of the
Clojure programming language.
Download from Wow! eBook <www.wowebook.com>
Download from Wow! eBook <www.wowebook.com>
brief contents
PART 1 FOUNDATIONS ......................................................................1
1
2
Drinking from the Clojure firehose 20
3
Dipping our toes in the pool 43
PART 2 DATA TYPES . .......................................................................59
PART 3 FUNCTIONAL PROGRAMMING............................................. 105
Being lazy and set in your ways 107
PART 4 LARGE-SCALE DESIGN ........................................................ 155
8
9
10
11
PART 5 TANGENTIAL CONSIDERATIONS.......................................... 275
12 ■
13 ■
Clojure changes the way you think 292
vii
Download from Wow! eBook <www.wowebook.com>
Download from Wow! eBook <www.wowebook.com>
contents
PART 1 FOUNDATIONS .....................................................1
Simplicity 4 ■ Freedom to focus 5 ■ Empowerment 5
Beauty 9 ■ Extreme flexibility 9 ■ Code is data 11
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
ix
Download from Wow! eBook <www.wowebook.com>
x
CONTENTS
2 Drinking from the Clojure firehose 20
Numbers 21 ■ Integers 22 ■ Floating-point numbers 22
Rationals 22 ■ Symbols 23 ■ Keywords 23 ■ Strings 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
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
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
3 Dipping our toes in the pool 43
What’s truth? 44 ■ Don’t create Boolean objects 44
Download from Wow! eBook <www.wowebook.com>
CONTENTS
xi
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
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
PART 2 DATA TYPES .......................................................59
4.1 Understanding precision 62
Truncation 62 ■ Promotion 63 ■ Overflow 64
Underflow 64 ■ Rounding errors 64
Why be rational? 66 ■ How to be rational 66 ■ Caveats of
How are keywords different from symbols? 68 ■ Qualifying your
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
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
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
Download from Wow! eBook <www.wowebook.com>
xii
CONTENTS
5.3 Lists: Clojure’s code form data structure 90
Lists like Lisps like 90 ■ Lists as stacks 91 ■ What lists
5.4 How to use persistent queues 91
A queue about nothing 92 ■ Putting things on 92 ■ Getting
things 93 ■ Taking things off 93
Basic properties of Clojure sets 94 ■ Keeping your sets in order with
sorted-set 94 ■ contains? 95 ■ clojure.set 96
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
PART 3 FUNCTIONAL PROGRAMMING . ...........................105
6 Being lazy and set in your ways 107
Defining immutability 108 ■ Being set in your ways—
6.2 Designing a persistent toy 110
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
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
Download from Wow! eBook <www.wowebook.com>
CONTENTS
xiii
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*
PART 4 LARGE-SCALE DESIGN. .......................................155
Syntax-quote, unquote, and splicing 160 ■ Macro rules of
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
Using macros to manage resources 171
Putting it all together: macros returning functions 173
Creating namespaces 179 ■ Expose only what’s needed 180
Declarative inclusions and exclusions 182
9.2 Exploring Clojure multimethods with the Universal
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
Download from Wow! eBook <www.wowebook.com>
xiv
CONTENTS
9.3 Types, protocols, and records 189
Records 189 ■ Protocols 192 ■ Building from a more primitive
9.4 Putting it all together: a fluent builder for chess moves 202
Java implementation 202 ■ Clojure implementation 204
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
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
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
Download from Wow! eBook <www.wowebook.com>
CONTENTS
xv
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
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
Sharing across threads 255 ■ Using Atoms in transactions 256
Safe mutation through locking 259 ■ Using Java’s explicit
Parallel tasks with promises 265 ■ Callback API to blocking
API 266 ■ Deterministic deadlocks 267
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
PART 5 TANGENTIAL CONSIDERATIONS . ....................... 275
Advantages of type adornment 278 ■ Type-hinting arguments
and returns 278 ■ Type-hinting objects 280
Ephemeral garbage 280 ■ Transients compare in efficiency to
Regaining one-at-a-time laziness 283
Download from Wow! eBook <www.wowebook.com>
xvi
CONTENTS
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
13 Clojure changes the way you think 292
A ubiquitous DSL 293 ■ Putting parentheses around the
specification 294 ■ A note about Clojure’s approach to
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
Download from Wow! eBook <www.wowebook.com>
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 get 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.
xvii
Download from Wow! eBook <www.wowebook.com>
xviii
FOREWORD
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
steve-yegge.blogspot.com
Download from Wow! eBook <www.wowebook.com>
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
xix
Download from Wow! eBook <www.wowebook.com>
xx
PREFACE
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. All 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 understanding of the joyfulness in Clojure,
for we believe its art is prelude to a new age of software development.
Download from Wow! eBook <www.wowebook.com>
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.
xxi
Download from Wow! eBook <www.wowebook.com>
xxii
ACKNOWLEDGMENTS
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 programming. 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.
Download from Wow! eBook <www.wowebook.com>
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
xxiii
Download from Wow! eBook <www.wowebook.com>
xxiv
ABOUT THIS BOOK
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’ll 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 knowledge. 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 apply 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 short 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.
Download from Wow! eBook <www.wowebook.com>
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 ignored. 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
Guy Steele and Gerald Sussman, the “Lambda
Gerald Sussman
Papers,” mng.bz/sU33.
Download from Wow! eBook <www.wowebook.com>
xxvi
ABOUT THIS BOOK
Foundational programming languages (continued)
Year
Language
Inventor(s)
Interesting reading
1983
C++
Bjarne Stroustrup
Bjarne Stroustrup, The Design and Evolution of C++
(Reading, MA: Addison-Wesley, 1994).
1986
Erlang
Telefonaktiebolaget
Joe Armstrong, “A History of Erlang,” Proceedings of
L. M. Ericsson
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!” http://learnyouahaskell.com/.
1995
Java
Sun Microsystems
David Bank, “The Java Saga,” Wired 3.12 (1995).
2007
Clojure?
Rich Hickey
You’re reading it.
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 journey 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 specific 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). Programmers 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.
Download from Wow! eBook <www.wowebook.com>
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 techniques, 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, meaning 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 interacting directly with the host platform.
Download from Wow! eBook <www.wowebook.com>
xxviii
ABOUT THIS BOOK
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 those 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
Download from Wow! eBook <www.wowebook.com>
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
exactly 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.
Download from Wow! eBook <www.wowebook.com>

xxx
ABOUT THIS BOOK
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 Cljr REPL is similar to the stock Clojure REPL, but with additional convenient
features as explained at http://github.com/fogus/cljr.
The book won’t proceed under the assumption that you’re 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 provide 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.
Download from Wow! eBook <www.wowebook.com>
ABOUT THIS BOOK
xxxi
About the cover illustration
The figure on the cover of The Joy of Clojure is captioned “The Confidence Man,” which,
in 19th century France, could mean anything from a healer or medicine man to a card
shark or money lender or traveling salesman. The illustration is taken from a 19th-
century edition of Sylvain Maréchal’s four-volume compendium of regional dress cus-
toms published in France. Each illustration is finely drawn and colored by hand. The
rich variety of Maréchal’s collection reminds us vividly of how culturally apart the
world’s towns and regions were just 200 years ago. Isolated from each other, people
spoke different dialects and languages. In the streets or in the countryside, it was easy
to identify where they lived and what their trade or station in life was just by their dress.
Dress codes have changed since then and the diversity by region, so rich at the
time, has faded away. It is now hard to tell apart the inhabitants of different conti-
nents, let alone different towns or regions. Perhaps we have traded cultural diversity
for a more varied personal life—certainly for a more varied and fast-paced technolog-
ical life.
At a time when it is hard to tell one computer book from another, Manning cele-
brates the inventiveness and initiative of the computer business with book covers
based on the rich diversity of regional life of two centuries ago, brought back to life by
Maréchal’s pictures.
Download from Wow! eBook <www.wowebook.com>
Download from Wow! eBook <www.wowebook.com>
Part 1
Foundations
Even the most elaborate mansion must begin with a firm if humble founda-
tion. We begin here by pouring a foundation of knowledge on which you’ll be
able to build a solid understanding about Clojure’s less familiar ways. This foun-
dation includes, among other things, the philosophy of programming underly-
ing Clojure, sturdy walls of data and functions, and REPLs and nil puns.
Download from Wow! eBook <www.wowebook.com>
Download from Wow! eBook <www.wowebook.com>
Clojure philosophy
This chapter covers
The Clojure way
Why a(nother) Lisp?
Functional programming
Why Clojure isn’t especially object-oriented
Learning a new language generally requires significant investment of thought and
effort, and it is only fair that programmers expect each language they consider
learning to justify that investment. Clojure was born out of creator Rich Hickey’s
desire to avoid many of the complications, both inherent and incidental, of manag-
ing state using traditional object-oriented techniques. Thanks to a thoughtful
design based in rigorous programming language research, coupled with a fervent
look toward practicality, Clojure has blossomed into an important programming
language playing an undeniably important role in the current state of the art in lan-
guage design. On one side of the equation, Clojure utilizes Software Transactional
Memory (STM), agents, a clear distinction between identity and value types, arbi-
trary polymorphism, and functional programming to provide an environment con-
ducive to making sense of state in general, and especially in the face of
concurrency. On the other side, Clojure shares a symbiotic relationship with the
3
Download from Wow! eBook <www.wowebook.com>
4
CHAPTER 1 Clojure philosophy
Java Virtual Machine, thus allowing prospective developers to avoid the costs of main-
taining yet another infrastructure while leveraging existing libraries.
In the grand timeline of programming language history, Clojure is an infant; but
its colloquialisms (loosely translated as “best practices” or idioms) are rooted1 in 50
years of Lisp, as well as 15 years of Java history. Additionally, the enthusiastic commu-
nity that has exploded since its introduction has cultivated its own set of unique idi-
oms. As mentioned in the preface, the idioms of a language help to define succinct
representations of more complicated expressions. Although we will certainly cover idi-
omatic Clojure code, we will also expand into deeper discussions of the “why” of the
language itself.
In this chapter, we’ll discuss the weaknesses in existing languages that Clojure was
designed to address, how it provides strength in those areas, and many of the design
decisions Clojure embodies. We’ll also look at some of the ways existing languages
have influenced Clojure, and define terms that will be used throughout the book.
1.1
The Clojure way
We’ll start slowly.
Clojure is an opinionated language—it doesn’t try to cover all paradigms or pro-
vide every checklist bullet-point feature. Instead it provides the features needed to
solve all kinds of real-world problems the Clojure way. To reap the most benefit from
Clojure, you’ll want to write your code with the same vision as the language itself. As
we walk through the language features in the rest of the book, we’ll mention not just
what a feature does, but why it’s there and how best to take advantage of it.
But before we get to that, we’ll first take a high-level view of some of Clojure’s most
important philosophical underpinnings. Figure 1.1 lists some broad goals that Rich
Hickey had in mind while designing Clojure and some of the more specific decisions
that are built into the language to support
these goals.
simplicity
As the figure illustrates, Clojure’s
pure
broad goals are formed from a confluence
functions
of supporting goals and functionality,
freedom
which we will touch on in the following
separation
empowerment
to focus
concise
of
concerns
subsections.
clarity
consistent
1.1.1
Simplicity
expressive
practical
direct
interop
It’s hard to write simple solutions to com-
plex problems. But every experienced
programmer has also stumbled on areas
Figure 1.1 Broad goals of Clojure: this figure
where we’ve made things more complex
shows some of the concepts that underlie the
than necessary, what you might call
Clojure philosophy, and how they intersect.
1 While drawing on the traditions of Lisps (in general) and Java, Clojure in many ways stands as a direct chal-
lenge to them for change.
Download from Wow! eBook <www.wowebook.com>
The Clojure way
5
incidental complexity as opposed to complexity that’s essential to the task at hand (Mose-
ley 2006). Clojure strives to let you tackle complex problems involving a wide variety
of data requirements, multiple concurrent threads, independently developed librar-
ies, and so on without adding incidental complexity. It also provides tools reducing
what at first glance may seem like essential complexity. The resulting set of features
may not always seem simple, especially when they’re still unfamiliar, but as you read
through this book we think you’ll come to see how much complexity Clojure helps
strip away.
One example of incidental complexity is the tendency of modern object-oriented
languages to require that every piece of runnable code be packaged in layers of class
definitions, inheritance, and type declarations. Clojure cuts through all this by cham-
pioning the pure function, which takes a few arguments and produces a return value
based solely on those arguments. An enormous amount of Clojure is built from such
functions, and most applications can be too, which means that there’s less to think
about when trying to solve the problem at hand.
1.1.2
Freedom to focus
Writing code is often a constant struggle against distraction, and every time a language
requires you to think about syntax, operator precedence, or inheritance hierarchies, it
exacerbates the problem. Clojure tries to stay out of your way by keeping things as sim-
ple as possible, not requiring you to go through a compile-and-run cycle to explore an
idea, not requiring type declarations, and so on. It also gives you tools to mold the lan-
guage itself so that the vocabulary and grammar available to you fit as well as possible
to your problem domain—Clojure is expressive. It packs a punch, allowing you to per-
form highly complicated tasks succinctly without sacrificing comprehensibility.
One key to delivering this freedom is a commitment to dynamic systems. Almost
everything defined in a Clojure program can be redefined, even while the program is
running: functions, multimethods, types, type hierarchies, and even Java method
implementations. Though redefining things on the fly might be scary on a production
system, it opens a world of amazing possibilities in how you think about writing pro-
grams. It allows for more experimentation and exploration of unfamiliar APIs, and it
adds an element of fun that can sometimes be impeded by more static languages and
long compilation cycles.
But Clojure’s not just about having fun. The fun is a by-product of giving program-
mers the power to be more productive than they ever thought imaginable.
1.1.3
Empowerment
Some programming languages have been created primarily to demonstrate some nug-
get of academia or to explore certain theories of computation. Clojure is not one of
these. Rich Hickey has said on numerous occasions that Clojure has value to the
degree that it lets you build interesting and useful applications.
Download from Wow! eBook <www.wowebook.com>
6
CHAPTER 1 Clojure philosophy
To serve this goal, Clojure strives to be practical—a tool for getting the job done. If
a decision about some design point in Clojure had to weigh the trade-offs between the
practical solution and a clever, fancy, or theoretically pure solution, usually the practi-
cal solution won out. Clojure could try to shield you from Java by inserting a compre-
hensive API between the programmer and the libraries, but this could make the use of
third-party Java libraries more clumsy. So Clojure went the other way: direct, wrapper-
free, compiles-to-the-same-bytecode access to Java classes and methods. Clojure strings
are Java strings; Clojure function calls are Java method calls—it’s simple, direct, and
practical.
The decision to use the Java Virtual Machine (JVM) itself is a clear example of this
practicality. The JVM has some technical weaknesses such as startup time, memory
usage, and lack of tail-call optimization 2 (TCO). But it’s also an amazingly practical plat-
form—it’s mature, fast, and widely deployed. It supports a variety of hardware and
operating systems and has a staggering number of libraries and support tools avail-
able, all of which Clojure can take advantage of because of this supremely practical
decision.
With direct method calls, proxy, gen-class, gen-interface (see chapter 10),
reify, definterface, deftype, and defrecord (see section 9.3), Clojure works hard
to provide a bevy of interoperability options, all in the name of helping you get your
job done. Practicality is important to Clojure, but many other languages are practical
as well. You’ll start to see some ways that Clojure really sets itself apart by looking at
how it avoids muddles.
1.1.4
Clarity
When beetles battle beetles in a puddle paddle battle and the beetle battle puddle is a
puddle in a bottle they call this a tweetle beetle bottle puddle paddle battle muddle.
—Dr. Seuss
Consider what might be described as a simple snippet of code in a language like
Python:
x = [5]
process(x)
x[0] = x[0] + 1
After executing this code, what’s the value of x? If you assume process doesn’t change
the contents of x at all, it should be [6], right? But how can you make that assump-
tion? Without knowing exactly what process does, and whatever function it calls does,
and so on, you can’t be sure at all.
Even if you’re sure process doesn’t change the contents of x, add multithreading
and now you have another whole set of concerns. What if some other thread changes
2
Don’t worry if you don't know what tail-call optimization is. Also don’t worry if you do know what TCO is and
think the JVM’s lack of it is a critical flaw for a Lisp or functional language such as Clojure. All your concerns
will be addressed in section 7.3. Until then, just relax.
Download from Wow! eBook <www.wowebook.com>
The Clojure way
7
x between the first and third lines? Worse yet, what if something is setting x at the
moment the third line is doing its assignment—are you sure your platform guarantees
an atomic write to that variable, or is it possible that the value will be a corrupted mix
of multiple writes? We could continue this thought exercise in hopes of gaining some
clarity, but the end result would be the same—what you have ends up not being clear
at all, but the opposite: a muddle.
Clojure strives for code clarity by providing tools to ward off several different kinds
of muddles. For the one just described, it provides immutable locals and persistent
collections, which together eliminate most of the single- and multithreaded issues all
at once.
You can find yourself in several other kinds of muddles when the language you’re
using merges unrelated behavior into a single construct. Clojure fights this by being
vigilant about separation of concerns. When things start off separated, it clarifies your
thinking and allows you to recombine them only when and to the extent that doing so
is useful for a particular problem. Table 1.1 contrasts common approaches that merge
concepts together in some other languages with separations of similar concepts in
Clojure that will be explained in greater detail throughout this book.
Table 1.1 Separation of concerns in Clojure
Conflated
Separated
Where
Object with mutable fields
Values from identities
Chapter 4 and section 5.1
Class acts as namespace for
Function namespaces from type
Sections 8.2 and 8.3
methods
namespaces
Inheritance hierarchy made of
Hierarchy of names from data and
Chapter 8
classes
functions
Data and methods bound
Data objects from functions
Sections 6.1 and 6.2 and
together lexically
chapter 8
Method implementations embed-
Interface declarations from func-
Sections 8.2 and 8.3
ded throughout class inheritance
tion implementations
chain
It can be hard at times to tease apart these concepts in our own minds, but accom-
plishing it can bring remarkable clarity and a sense of power and flexibility that’s
worth the effort. With all these different concepts at your disposal, it’s important that
the code and data you work with express this variety in a consistent way.
1.1.5
Consistency
Clojure works to provide consistency in two specific ways: consistency of syntax and of
data structures.
Consistency of syntax is about the similarity in form between related concepts. One
simple but powerful example of this is the shared syntax of the for and doseq macros.
Download from Wow! eBook <www.wowebook.com>
8
CHAPTER 1 Clojure philosophy
They don’t do the same thing—for returns a lazy seq whereas doseq is for generating
side effects—but both support the same mini-language of nested iteration, destructur-
ing, and :when and :while guards. The similarities stand out when comparing the fol-
lowing examples:
(for [x [:a :b], y (range 5) :when (odd? y)] [x y])
;=> ([:a 1] [:a 3] [:b 1] [:b 3])
(doseq [x [:a :b], y (range 5) :when (odd? y)] (prn x y))
; :a 1
; :a 3
; :b 1
; :b 3
;=> nil
The value of this similarity is having to learn only one basic syntax for both situations,
as well as the ease with which you can convert any particular usage of one form to the
other if that becomes necessary.
Likewise, the consistency of data structures is the deliberate design of all of Clo-
jure’s persistent collection types to provide interfaces as similar to each other as possi-
ble, as well as to make them as broadly useful as possible. This is actually an extension
of the classic Lisp “code is data” philosophy. Clojure data structures aren’t used just
for holding large amounts of application data, but also to hold the expression ele-
ments of the application itself. They’re used to describe destructuring forms and to
provide named options to various built-in functions. Where other object-oriented lan-
guages might encourage applications to define multiple incompatible classes to hold
different kinds of application data, Clojure encourages the use of compatible map-like
objects.
The benefit of this is that the same set of functions designed to work with Clojure
data structures can be applied to all these contexts: large data stores, application
code, and application data objects. You can use into to build any of these types, seq to
get a lazy seq to walk through them, filter to select elements of any of them that sat-
isfy a particular predicate, and so on. Once you’ve grown accustomed to having the
richness of all these functions available everywhere, dealing with a Java or C++ applica-
tion’s Person or Address class will feel constraining.
Simplicity, freedom to focus, empowerment, consistency, and clarity.
Nearly every element of the Clojure programming language is designed to pro-
mote these goals. When writing Clojure code, if you keep in mind the desire to maxi-
mize simplicity, empowerment, and the freedom to focus on the real problem at
hand, we think you’ll find Clojure provides you the tools you need to succeed.
1.2
Why a(nother) Lisp?
By relieving the brain of all unnecessary work, a good notation sets it free to concen-
trate on more advanced problems.
—Alfred North Whitehead
Download from Wow! eBook <www.wowebook.com>
Why a(nother) Lisp?
9
Go to any open source project hosting site and perform a search for the term “Lisp
interpreter.” You’ll likely get a cyclopean mountain3 of results from this seemingly
innocuous term. The fact of the matter is that the history of computer science is lit-
tered (Fogus 2009) with the abandoned husks of Lisp implementations. Well-inten-
tioned Lisps have come and gone and been ridiculed along the way, and still
tomorrow the search results will have grown almost without bounds. Bearing in mind
this legacy of brutality, why would anyone want to base their brand-new programming
language on the Lisp model?
1.2.1
Beauty
Lisp has attracted some of the brightest minds in the history of computer science. But
an argument from authority is insufficient, so you shouldn’t judge Lisp on this alone.
The real value in the Lisp family of languages can be directly observed through the
activity of using it to write applications. The Lisp style is one of expressivity and
empowerment, and in many cases outright beauty. Joy awaits the Lisp neophyte. The
original Lisp language as defined by John McCarthy in his earth-shattering essay
“Recursive Functions of Symbolic Expressions and Their Computation by Machine,
Part I” (McCarthy 1960) defined the whole language in terms of only seven functions
and two special forms: atom, car, cdr, cond, cons, eq, quote, lambda, and label.
Through the composition of those nine forms, McCarthy was able to describe the
whole of computation in a way that takes your breath away. Computer programmers
are perpetually in search of beauty, and more often than not, this beauty presents
itself in the form of simplicity. Seven functions and two special forms. It doesn’t get
more beautiful than that.
1.2.2
Extreme flexibility
Why has Lisp persevered for more than 50 years while countless other languages have
come and gone? There are probably complex reasons, but chief among them is likely
the fact that Lisp as a language genotype (Tarver 2008) fosters language flexibility in
the extreme. Newcomers to Lisp are sometimes unnerved by its pervasive use of
parentheses and prefix notation, which is different than non-Lisp programming lan-
guages. The regularity of this behavior not only reduces the number of syntax rules
you have to remember, but also makes the writing of macros trivial. We’ll look at mac-
ros in more detail in chapter 8, but to whet your appetite we’ll take a brief look at one
now. It’s an example that we’ll get working on in a moment:
(defn query [max]
(SELECT [a b c]
(FROM X
(LEFT-JOIN Y :ON (= X.a Y.b)))
(WHERE (AND (< a 5) (< b ~max)))))
3 ...of madness.
Download from Wow! eBook <www.wowebook.com>
10
CHAPTER 1 Clojure philosophy
We hope some of those words look familiar to you, because this isn’t a book on SQL.
Regardless, our point here is that Clojure doesn’t have SQL support built in. The
words SELECT, FROM, and so forth aren’t built-in forms. They’re also not regular func-
tions, because if SELECT were, then the use of a, b, and c would be an error, because
they haven’t been defined yet.
So what does it take to define a domain-specific language (DSL) like this in Clo-
jure? Well, it’s not production-ready code and doesn’t tie into any real database serv-
ers; but with just one macro and the three functions shown in listing 1.1, the
preceding query returns these handy values:
(query 5)
;=> ["SELECT a, b, c FROM X LEFT JOIN Y ON (X.a = Y.b)
WHERE ((a < 5) AND (b < ?))"
[5]]
Note that some words such as FROM and ON are taken directly from the input expres-
sion, whereas others such as ~max and AND are treated specially. The max that was given
the value 5 when the query was called is extracted from the literal SQL string and pro-
vided in a separate vector, perfect for using in a prepared query in a way that will
guard against SQL-injection attacks. The AND form was converted from the prefix nota-
tion of Clojure to the infix notation required by SQL.
Listing 1.1 A domain-specific language for embedding SQL queries in Clojure
(ns joy.sql
(:use [clojure.string :as str :only []])
Use core
(defn expand-expr [expr]
string functions
(if (coll? expr)
(if (= (first expr) ùnquote)
Handle unsafe literals
"?"
(let [[op & args] expr]
(str "(" (str/join (str " " op " ")
(map expand-expr args)) ")")))
Convert prefix
expr))
to infix
(declare expand-clause)
Support each
(def clause-map
kind of clause
{'SELECT (fn [fields & clauses]
(apply str "SELECT " (str/join ", " fields)
(map expand-clause clauses)))
'FROM (fn [table & joins]
(apply str " FROM " table
(map expand-clause joins)))
'LEFT-JOIN (fn [table on expr]
(str " LEFT JOIN " table
" ON " (expand-expr expr)))
'WHERE (fn [expr]
Call
(str " WHERE " (expand-expr expr)))})
appropriate
(defn expand-clause [[op & args]]
converter
(apply (clause-map op) args))
Download from Wow! eBook <www.wowebook.com>
Why a(nother) Lisp?
11
(defmacro SELECT [& args]
Provide main
[(expand-clause (cons 'SELECT args))
entrypoint macro
(vec (for [n (tree-seq coll? seq args)
:when (and (coll? n) (= (first n) ùnquote))]
(second n)))])
But the point here isn’t that this is a particularly good SQL DSL—more complete ones
are available.4 Our point is that once you have the skill to easily create a DSL like this,
you’ll recognize opportunities to define your own that solve much narrower,
application-specific problems than SQL does. Whether it’s a query language for an
unusual non-SQL datastore, a way to express functions in some obscure math disci-
pline, or some other application we as authors can’t imagine, having the flexibility to
extend the base language like this, without losing access to any of the language’s own
features, is a game-changer.
Although we shouldn’t get into too much detail about the implementation, take
a brief look at listing 1.1 and follow along as we discuss important aspects of its
implementation.
Reading from the bottom up, you’ll notice the main entry point, the SELECT
macro. This returns a vector of two items—the first is generated by calling expand-
clause, which returns the converted query string, whereas the second is another vec-
tor of expressions marked by ~ in the input. The ~ is known as unquote and we discuss
its more common uses in chapter 8. Also note the use of tree-seq here to succinctly
extract items of interest from a tree of values, namely the input expression.
The expand-clause function takes the first word of a clause, looks it up in the
clause-map, and calls the appropriate function to do the actual conversion from Clo-
jure s-expression to SQL string. The clause-map provides the specific functionality
needed for each part of the SQL expression: inserting commas or other SQL syntax,
and sometimes recursively calling expand-clause when subclauses need to be con-
verted. One of these is the WHERE clause, which handles the general conversion of pre-
fix expressions to the infix form required by SQL by delegating to the expand-expr
function.
Overall, the flexibility of Clojure demonstrated in this example comes largely from
the fact that macros accept code forms, such as the SQL DSL example we showed, and
can treat them as data—walking trees, converting values, and more. This works not
only because code can be treated as data, but because in a Clojure program, code is
data.
1.2.3
Code is data
The notion of “code is data” is difficult to grasp at first. Implementing a programming
language where code shares the same footing as its comprising data structures presup-
poses a fundamental malleability of the language itself. When your language is repre-
sented as the inherent data structures, the language itself can manipulate its own
4 One of note is ClojureQL at http://gitorious.org/clojureql.
Download from Wow! eBook <www.wowebook.com>
12
CHAPTER 1 Clojure philosophy
structure and behavior (Graham 1995). You may have visions of Ouroboros after read-
ing the previous sentence, and that wouldn’t be inappropriate, because Lisp can be
likened to a self-licking lollypop—more formally defined as homoiconicity. Lisp’s
homoiconicity takes a great conceptual leap in order to fully grasp, but we’ll lead you
toward that understanding throughout this book in hopes that you too will come to
realize the inherent power.
There’s a joy in learning Lisp for the first time, and if that’s your experience com-
ing into this book then we welcome you—and envy you.
1.3
Functional programming
Quick, what does functional programming mean? Wrong answer.
Don’t be too discouraged, however—we don’t really know the answer either. Func-
tional programming is one of those computing terms5 that has a nebulous definition.
If you ask 100 programmers for their definition, you’ll likely receive 100 different
answers. Sure, some definitions will be similar, but like snowflakes, no two will be
exactly the same. To further muddy the waters, the cognoscenti of computer science
will often contradict one another in their own independent definitions. Likewise, the
basic structure of any definition of functional programming will be different depend-
ing on whether your answer comes from someone who favors writing their programs
in Haskell, ML, Factor, Unlambda, Ruby, or Qi. How can any person, book, or lan-
guage claim authority for functional programming? As it turns out, just as the multi-
tudes of unique snowflakes are all made mostly of water, the core of functional
programming across all meanings has its core tenets.
1.3.1
A workable definition of functional programming
Whether your own definition of functional programming hinges on the lambda calcu-
lus, monadic I/O, delegates, or java.lang.Runnable, your basic unit of currency is
likely to be some form of procedure, function, or method—herein lies the root. Func-
tional programming concerns and facilitates the application and composition of func-
tions. Further, for a language to be considered functional, its notion of function must
be first-class. The functions of a language must be able to be stored, passed, and
returned just like any other piece of data within that language. It’s beyond this core
concept that the definitions branch toward infinity, but thankfully, it’s enough to start.
Of course, we’ll also present a further definition of Clojure’s style of functional pro-
gramming that includes such topics as purity, immutability, recursion, laziness, and
referential transparency, but those will come later in chapter 7.
1.3.2
The implications of functional programming
Object-oriented programmers and functional programmers will often see and solve a
problem in different ways. Whereas an object-oriented mindset will foster the
5 Quick, what’s the definition of combinator? How about cloud computing? Enterprise? SOA? Web 2.0? Real-
world? Hacker? Often it seems that the only term with a definitive meaning is “yak shaving.”
Download from Wow! eBook <www.wowebook.com>
Why Clojure isn’t especially object-oriented
13
approach of defining an application domain as a set of nouns (classes), the functional
mind will see the solution as the composition or verbs (functions). Though both pro-
grammers may in all likelihood generate equivalent results, the functional solution
will be more succinct, understandable, and reusable. Grand claims indeed! We hope
that by the end of this book you’ll agree that functional programming fosters ele-
gance in programming. It takes a shift in mindset to start from thinking in nouns to
arrive at thinking in verbs, but the journey will be worthwhile. In any case, we think
there’s much that you can take from Clojure to apply to your chosen language—if
only you approach the subject with an open mind.
1.4
Why Clojure isn’t especially object-oriented
Elegance and familiarity are orthogonal.
—Rich Hickey
Clojure was born out of frustration provoked in large part by the complexities of con-
current programming, complicated by the weaknesses of object-oriented program-
ming in facilitating it. This section explores these weaknesses and lays the groundwork
for why Clojure is functional and not object-oriented.
1.4.1
Defining terms
Before we begin, it’s useful to define terms.6
The first important term to define is time. Simply put, time refers to the relative
moments when events occur. Over time, the properties associated with an entity—
both static and changing, singular or composite—will form a concrescence (White-
head 1929) and be logically deemed its identity. It follows from this that at any given
time, a snapshot can be taken of an entity’s properties defining its state. This notion of
state is an immutable one because it’s not defined as a mutation in the entity itself, but
only as a manifestation of its properties at a given moment in time. Imagine a child’s
flip book, as seen in figure 1.2, to understand the terms fully.
It’s important to note that in the canon of object-oriented programming, there’s
no clear distinction between state and identity. In other words, these two ideas are
Figure 1.2 The Runner: a child’s flip book serves to
illustrate Clojure’s notions of state, time, and identity. The
book itself represents the identity. Whenever you wish to
show a change in the illustration, you draw another picture
and add it to the end of your flip book. The act of flipping the
pages therefore represents the states over time of the image
within. Stopping at any given page and observing the
particular picture represents the state of the Runner at that
moment in time.
6 These terms are also defined and elaborated on in Rich Hickey’s presentation, “Are We There Yet?” (Hickey
2009).
Download from Wow! eBook <www.wowebook.com>


14
CHAPTER 1 Clojure philosophy
Figure 1.3 The Mutable Runner: modeling state change with
mutation requires that you stock up on erasers. Your book
becomes a single page, requiring that in order to model
changes, you must physically erase and redraw the parts of
the picture requiring change. Using this model, you should see
that mutation destroys all notion of time, and state and
identity become one.
conflated into what’s commonly referred to as mutable state. The classical object-
oriented model allows unrestrained mutation of object properties without a willing-
ness to preserve historical states. Clojure’s implementation attempts to draw a clear
separation between an object’s state and identity as they relate to time. To state the dif-
ference to Clojure’s model in terms of the aforementioned flip book, the mutable
state model is different, as seen in figure 1.3.
Immutability lies at the cornerstone of Clojure, and much of the implementation
ensures that immutability is supported efficiently. By focusing on immutability, Clo-
jure eliminates entirely the notion of mutable state (which is an oxymoron) and instead
expounds that most of what’s meant by objects are instead values. Value by definition
refers to an object’s constant representative7 amount, magnitude, or epoch. You
might ask yourself: what are the implications of the value-based programming seman-
tics of Clojure?
Naturally, by adhering to a strict model of immutability, concurrency suddenly
becomes a simpler (although not simple) problem, meaning if you have no fear that
an object’s state will change, then you can promiscuously share it without fear of con-
current modification. Clojure instead isolates value change to its reference types, as
we’ll show in chapter 11. Clojure’s reference types provide a level of indirection to an
identity that can be used to obtain consistent, if not always current, states.
1.4.2
Imperative “baked in”
Imperative programming is the dominant programming paradigm today. The most
unadulterated definition of an imperative programming language is one where a
sequence of statements mutates program state. During the writing of this book (and
likely for some time beyond), the preferred flavor of imperative programming is the
object-oriented style. This fact isn’t inherently bad, because there are countless suc-
cessful software projects built using object-oriented imperative programming tech-
niques. But from the context of concurrent programming, the object-oriented
imperative model is self-cannibalizing. By allowing (and even promoting) unre-
strained mutation via variables, the imperative model doesn’t directly support concur-
rency. Instead, by allowing a maenadic approach to mutation, there are no guarantees
that any variable contains the expected value. Object-oriented programming takes this
one step further by aggregating state in object internals. Though individual methods
may be thread-safe through locking schemes, there’s no way to ensure a consistent
7 Some entities have no representative value—Pi is an example. But in the realm of computing, where we’re
ultimately referring to finite things, this is a moot point.
Download from Wow! eBook <www.wowebook.com>
Why Clojure isn’t especially object-oriented
15
object state across multiple method calls without expanding the scope of potentially
complex locking scheme(s). Clojure instead focuses on functional programming,
immutability, and the distinction between state, time, and identity. But object-oriented
programming isn’t a lost cause. In fact, there are many aspects that are conducive to
powerful programming practice.
1.4.3
Most of what OOP gives you, Clojure provides
It should be made clear that we’re not attempting to mark object-oriented program-
mers as pariahs. Instead, it’s important that we identify the shortcomings of object-
oriented programming (OOP) if we’re ever to improve our craft. In the next few sub-
sections we’ll also touch on the powerful aspects of OOP and how they’re adopted,
and in some cases improved, by Clojure.
POLYMORPHISM AND THE EXPRESSION PROBLEM
Polymorphism is the ability of a function or method to have different definitions
depending on the type of the target object. Clojure provides polymorphism via both
multimethods and protocols, and both mechanisms are more open and extensible
than polymorphism in many languages.
Listing 1.2 Clojure’s polymorphic protocols
(defprotocol Concatenatable
(cat [this other]))
(extend-type String
Concatenatable
(cat [this other]
(.concat this other)))
(cat "House" " of Leaves")
;=> "House of Leaves"
What we’ve done in listing 1.2 is to define a protocol named Concatenatable that
groups one or more functions (in this case only one, cat) that define the set of func-
tions provided. That means the function cat will work for any object that fully satisfies
the protocol Concatenatable. We then extend this protocol to the String class and
define the specific implementation—a function body that concatenates the argument
other onto the string this. We can also extend this protocol to another type:
(extend-type java.util.List
Concatenatable
(cat [this other]
(concat this other)))
(cat [1 2 3] [4 5 6])
;=> (1 2 3 4 5 6)
So now the protocol has been extended to two different types, String and
java.util.List, and thus the cat function can be called with either type as its first
argument —the appropriate implementation will be invoked.
Download from Wow! eBook <www.wowebook.com>
16
CHAPTER 1 Clojure philosophy
Note that String was already defined (in this case by Java itself) before we defined
the protocol, and yet we were still able to successfully extend the new protocol to it.
This isn’t possible in many languages. For example, Java requires that you define all
the method names and their groupings (known as interfaces) before you can define a
class that implements them, a restriction that’s known as the expression problem.
THE EXPRESSION PROBLEM The expression problem refers to the desire to
implement an existing set of abstract methods for an existing concrete class
without having to change the code that defines either. Object-oriented lan-
guages allow you to implement an existing abstract method in a concrete class
you control (interface inheritance), but if the concrete class is outside your
control, the options for making it implement new or existing abstract meth-
ods tend to be sparse. Some dynamic languages such as Ruby and JavaScript
provide partial solutions to this problem by allowing you to add methods to
an existing concrete object, a feature sometimes known as monkey-patching.
A Clojure protocol can be extended to any type where it makes sense, even those that
were never anticipated by the original implementor of the type or the original
designer of the protocol. We’ll dive deeper into Clojure’s flavor of polymorphism in
chapter 9, but we hope now you have a basic idea of how it works.
SUBTYPING AND INTERFACE-ORIENTED PROGRAMMING
Clojure provides a form of subtyping by allowing the creation of ad-hoc hierarchies.
We’ll delve into leveraging the ad-hoc hierarchy facility later, in section 9.2. Likewise,
Clojure provides a capability similar to Java’s interfaces via its protocol mechanism. By
defining a logically grouped set of functions, you can begin to define protocols to which
data-type abstractions must adhere. This abstraction-oriented programming model is key
in building large-scale applications, as you’ll discover in section 9.3 and beyond.
ENCAPSULATION
If Clojure isn’t oriented around classes, then how does it provide encapsulation?
Imagine that you need a simple function that, given a representation of a chessboard
and a coordinate, returns a simple representation of the piece at the given square. To
keep the implementation as simple as possible, we’ll use a vector containing a set of
characters corresponding to the colored chess pieces, as shown next.
Listing 1.3 A simple chessboard representation in Clojure
(ns joy.chess)
(defn initial-board []
[\r \n \b \q \k \b \n \r
\p \p \p \p \p \p \p \p
Lowercase dark
\- \- \- \- \- \- \- \-
\- \- \- \- \- \- \- \-
\- \- \- \- \- \- \- \-
\- \- \- \- \- \- \- \-
\P \P \P \P \P \P \P \P
Uppercase light
\R \N \B \Q \K \B \N \R])
Download from Wow! eBook <www.wowebook.com>
Why Clojure isn’t especially object-oriented
17
There’s no need to complicate matters with the
8
\r
\n
\b
\q
\k
\b
\n
\r
chessboard representation; chess is hard
0
1
2
3
4
5
6
7
enough. This data structure in the code corre-
7
\p
\p
\p
\p
\p
\p
\p
\p
8
9
10
11
12
13
14
15
sponds directly to an actual chessboard in the
6
16
17
18
19
20
21
22
23
starting position, as shown in figure 1.4.
5
From the figure, you can gather that the
24
25
26
27
28
29
30
31
black pieces are lowercase characters and white 4
32
33
34
35
36
37
38
39
pieces are uppercase. This kind of structure is 3
likely not optimal, but it’s a good start. You can
40
41
42
43
44
45
46
47
ignore the actual implementation details for 2
\P
\P
\P
\P
\P
\P
\P
\P
48
49
50
51
52
53
54
55
now and focus on the client interface to query
\R
\N
\B
\Q
\K
\B
\N
\R
1
56
57
58
59
60
61
62
63
the board for square occupations. This is a per-
a b c d e f g h
fect opportunity to enforce encapsulation to
avoid drowning the client in board implementa-
Figure 1.4
The corresponding chessboard layout
tion details. Fortunately, programming lan-
guages with closures automatically support a form of encapsulation (Crockford 2008)
to group functions with their supporting data.8
The functions in listing 1.4 are self-evident in their intent9 and are encapsulated at
the level of the namespace joy.chess through the use of the defn- macro that creates
namespace private functions. The command for using the lookup function in this case
would be (joy.chess/lookup (initial-board) "a1").
Listing 1.4 Querying the squares of a chessboard
(def *file-key* \a)
(def *rank-key* \0)
(defn- file-component [file]
Calculate file
(- (int file) (int *file-key*)))
(horizontal) projection
(defn- rank-component [rank]
Calculate rank
(* 8 (- 8 (- (int rank) (int *rank-key*)))))
(vertical) projection
(defn- index [file rank]
(+ (file-component file) (rank-component rank)))
Project 1D layout onto
(defn lookup [board pos]
logical 2D chessboard
(let [[file rank] pos]
(board (index file rank))))
Clojure’s namespace encapsulation is the most prevalent form of encapsulation that
you’ll encounter when exploring idiomatic source code. But the use of lexical clo-
sures provides more options for encapsulation: block-level encapsulation, as shown in
listing 1.5, and local encapsulation, both of which effectively aggregate unimportant
details within a smaller scope.
8
This form of encapsulation is described as the module pattern. But the module pattern as implemented with
JavaScript provides some level of data hiding also, whereas in Clojure—not so much.
9
And as a nice bonus, these functions can be generalized to project a 2D structure of any size to a 1D represen-
tation—which we leave to you as an exercise.
Download from Wow! eBook <www.wowebook.com>
18
CHAPTER 1 Clojure philosophy
Listing 1.5 Using block-level encapsulation
(letfn [(index [file rank]
(let [f (- (int file) (int \a))
r (* 8 (- 8 (- (int rank) (int \0))))]
(+ f r)))]
(defn lookup [board pos]
(let [[file rank] pos]
(board (index file rank)))))
It's often a good idea to aggregate relevant data, functions, and macros at their most
specific scope. You’d still call lookup as before, but now the ancillary functions aren’t
readily visible to the larger enclosing scope—in this case, the namespace joy.chess.
In the preceding code, we’ve taken the file-component and rank-component func-
tions and the *file-key* and *rank-key* values out of the namespace proper and
rolled them into a block-level index function defined with the body of the letfn
macro. Within this body, we then define the lookup function, thus limiting the client
exposure to the chessboard API and hiding the implementation specific functions and
forms. But we can further limit the scope of the encapsulation, as shown in the next
listing, by shrinking the scope even more to a truly function-local context.
Listing 1.6 Local encapsulation
(defn lookup2 [board pos]
(let [[file rank] (map int pos)
[fc rc] (map int [\a \0])
f (- file fc)
r (* 8 (- 8 (- rank rc)))
index (+ f r)]
(board index)))
Finally, we’ve now pulled all of the implementation-specific details into the body of
the lookup2 function itself. This localizes the scope of the index function and all aux-
iliary values to only the relevant party—lookup2. As a nice bonus, lookup2 is simple
and compact without sacrificing readability. But Clojure eschews the notion of data-
hiding encapsulation featured prominently in most object-oriented languages.
NOT EVERYTHING IS AN OBJECT
Finally, another downside to object-oriented programming is the tight coupling
between function and data. In fact, the Java programming language forces you to
build programs entirely from class hierarchies, restricting all functionality to contain-
ing methods in a highly restrictive “Kingdom of Nouns” (Yegge 2006). This environ-
ment is so restrictive that programmers are often forced to turn a blind eye to
awkward attachments of inappropriately grouped methods and classes. It’s because of
the proliferation of this stringent object-centric viewpoint that Java code tends toward
being verbose and complex (Budd 1995). Clojure functions are data, yet this in no
way restricts the decoupling of data and the functions that work upon them. Many of
what programmers perceive to be classes are data tables that Clojure provides via
Download from Wow! eBook <www.wowebook.com>
Summary
19
maps10 and records. The final strike against viewing everything as an object is that
mathematicians view little (if anything) as objects (Abadi 1996). Instead, mathematics
is built on the relationships between one set of elements and another through the
application of functions.
1.5
Summary
We’ve covered a lot of conceptual ground in this chapter, but it was necessary in order
to define the terms used throughout the remainder of the book. Likewise, it’s impor-
tant to understand Clojure’s underpinnings in order to frame the discussion for the
rest of the book. If you’ve taken in the previous sections and internalized them, then
congratulations: you have a solid basis for proceeding to the rest of the book. But if
you’re still not sure what to make of Clojure, it’s okay—we understand that it may be a
lot to take in all at once. Understanding will come gradually as we piece together Clo-
jure’s story. For those of you coming from a functional programming background,
you’ll likely have recognized much of the discussion in the previous sections, but per-
haps with some surprising twists. Conversely, if your background is more rooted in
object-oriented programming, then you may get the feeling that Clojure is very differ-
ent than you’re accustomed to. Though in many ways this is true, in the coming chap-
ters you’ll see how Clojure elegantly solves many of the problems that you deal with on
a daily basis. Clojure approaches solving software problems from a different angle
than classical object-oriented techniques, but it does so having been motivated by
their fundamental strengths and shortcomings.
With this conceptual underpinning in place, it’s time to make a quick run through
Clojure’s technical basics and syntax. We’ll be moving fairly quickly, but no faster than
necessary to get to the deeper topics in following chapters. So hang on to your REPL,
here we go...
10 See section 5.6 for more discussion on this idea.
Download from Wow! eBook <www.wowebook.com>
Drinking from
the Clojure firehose
This chapter covers
Scalars
Putting things together: collections
Making things happen: functions
Vars
Locals, loops, and blocks
Preventing things from happening: quoting
Leveraging Java via interop
Exceptional circumstances
Namespaces
This chapter provides a quick tour of the bare necessities—the things you’ll need
to know to understand the rest of this book. If you’ve been programming with Clo-
jure for a while, this may be a review, but otherwise it should give you everything
you need to start writing Clojure code. In most cases throughout this chapter, the
examples provided will be perfunctory in order to highlight the immediate point.
20
Download from Wow! eBook <www.wowebook.com>
Scalars
21
Later in the book we’ll build on these topics and many more, so don’t worry if you
don’t quite grasp every feature now—you’ll get there.
Interaction with Clojure is often performed at the Read-Eval-Print Loop (REPL).
When starting a new REPL session, you’re presented with a simple prompt:
user>
The user prompt refers to the top-level namespace of the default REPL. It’s at this
point that Clojure waits for input expressions. Valid Clojure expressions consist of
numbers, symbols, keywords, booleans, characters, functions, function calls, macros,
strings, literal maps, vectors, and sets. Some expressions, such as numbers, strings, and
keywords, are self-evaluating—when entered, they evaluate to themselves. The Clojure
REPL also accepts source comments, which are marked by the semicolon ; and con-
tinue to a newline:
user> 42 ; numbers evaluate to themselves
;=> 42
user> "The Misfits" ; strings do too
;=> "The Misfits"
user> :pyotr ; as do keywords
;=> :pyotr
Now that we’ve seen several scalar data types, we’ll take a closer look at each of them.
2.1
Scalars
The Clojure language has a rich set of data types. Like most programming languages,
it provides scalar types such as integers, strings, and floating-point numbers, each rep-
resenting a single unit of data. Clojure provides several different categories of scalar
data types: integers, floats, rationals, symbols, keywords, strings, characters, booleans,
and regex patterns. In this section, we’ll address most of these1 categories in turn, pro-
viding examples of each.
2.1.1
Numbers
A number can consist of only the digits 0-9, a decimal point (.), a sign (+ or -), and an
optional e for numbers written in exponential notation. In addition to these elements,
numbers in Clojure can take either octal or hexadecimal form and also include an
optional M, that flags a number as a decimal requiring arbitrary precision: an impor-
tant aspect of numbers in Clojure. In many programming languages, the precision2 of
numbers is restricted by the host platform, or in the case of Java and C#, defined by
the language specification. Clojure on the other hand uses the host language’s primi-
tive numbers when appropriate, but rolls over to the arbitrarily precise versions when
needed, or when explicitly specified.
1
We won’t look at regular expression patterns here, but for details on everything regex-related you can flip for-
ward to section 4.6.
2
With caveats, as we’ll describe in chapter 4.
Download from Wow! eBook <www.wowebook.com>
22
CHAPTER 2 Drinking from the Clojure firehose
2.1.2
Integers
Integers comprise the whole number set, both positive and negative. Any number
starting with an optional sign or digit followed exclusively by digits is considered and
stored as an integer. Integers in Clojure can theoretically take an infinitely large value,
although in practice the size is limited by the memory available. The following num-
bers are recognized by Clojure as integers:
42
+9
-107
991778647261948849222819828311491035886734385827028118707676848307166514
The following illustrates the use of decimal, hexadecimal, octal, radix-32, and binary
literals, respectively, all representing the same number:
[127 0x7F 0177 32r3V 2r01111111]
;=> [127 127 127 127 127]
The radix notation supports up to base 36. Adding signs to the front of each of the
integer literals is also legal.
2.1.3
Floating-point numbers
Floating-point numbers are the decimal expansion of rational numbers. Like Clo-
jure’s implementation of integers, the floating-point values are arbitrarily precise.3
Floating-point numbers can take the traditional form of some number of digits and
then a decimal point, followed by some number of digits. But floating-point numbers
can also take an exponential form (scientific notation) where a significant part is fol-
lowed by an exponent part separated by a lower or uppercase E. The following num-
bers are examples of valid floating-point numbers:
1.17
+1.22
-2.
366e7
32e-14
10.7e-3
Numbers are largely the same across most programming languages, so we’ll move on
to some scalar types that are more unique to Lisp and Lisp-inspired languages.
2.1.4
Rationals
Clojure provides a rational type in addition to integer and floating-point numbers.
Rational numbers offer a more compact and precise representation of a given value
over floating-point. Rationals are represented classically by an integer numerator and
denominator, and that’s exactly how they’re represented in Clojure. The following
numbers are examples of valid rational numbers:
3 With some caveats, as we’ll discuss in section 4.1.
Download from Wow! eBook <www.wowebook.com>
Scalars
23
22/7
7/22
1028798300297636767687409028872/88829897008789478784
-103/4
Something to note about rational numbers in Clojure is that they’ll be simplified if
they can—the rational 100/4 will resolve to the integer 25.
2.1.5
Symbols
Symbols in Clojure are objects in their own right, but are often used to represent
another value. When a number or a string is evaluated, you get back exactly the same
object, but when a symbol is evaluated, you’ll get back whatever value that symbol is
referring to in the current context. In other words, symbols are typically used to refer
to function parameters, local variables, globals, and Java classes.
2.1.6
Keywords
Keywords are similar to symbols, except that they always evaluate to themselves. You’re
likely to see the use of keywords far more in Clojure than symbols. The form of a key-
word’s literal syntax is as follows:
:chumby
:2
:?
:ThisIsTheNameOfaKeyword
Although keywords are prefixed by a colon :, it’s only part of the literal syntax and not
part of the name itself. We go into further detail about keywords in section 4.3.
2.1.7
Strings
Strings in Clojure are represented similarly to the way they’re used in many program-
ming languages: a string is any sequence of characters enclosed within a set of double
quotes, including newlines, as shown:
"This is a string"
"This is also a
String"
Both will be stored as written, but when printed at the REPL, multiline strings will
include escapes for the literal newline characters like "This is also a\n String".
2.1.8
Characters
Clojure characters are written with a literal syntax prefixed with a backslash and are
stored as Java Character objects, as shown:
\a ; The character lowercase a
\A ; The character uppercase A
\u0042 ; The unicode character uppercase B
\\ ; The back-slash character \
\u30DE ; The unicode katakana character ?
Download from Wow! eBook <www.wowebook.com>
24
CHAPTER 2 Drinking from the Clojure firehose
And that’s it for Clojure’s scalar data types. In the next section, we’ll discuss Clojure’s
collection data types, which is where the real fun begins.
2.2
Putting things together: collections
We’ll cover the collection types in greater detail in chapter 5, but because Clojure pro-
grams are made up of various kinds of literal collections, it’s helpful to at least glance
at the basics of lists, vectors, maps, and sets.
2.2.1
Lists
Lists are the classic collection type in List Processing languages, and Clojure is no
exception. Literal lists are written with parentheses:
(yankee hotel foxtrot)
When a list is evaluated, the first item of the list —yankee in this case—will be resolved
to a function, macro, or special form. If yankee is a function, the remaining items in the
list will be evaluated in order, and the results will be passed to yankee as its parameters.
FORMS A form is any Clojure object meant to be evaluated, including but not
limited to lists, vectors, maps, numbers, keywords, and symbols. A special form
is a form with special syntax or special evaluation rules that are typically not
implemented using the base Clojure forms. An example of a special form is
the . (dot) operator used for Java interoperability purposes.
If on the other hand yankee is a macro or special form, the remaining items in the list
aren’t necessarily evaluated, but are processed as defined by the macro or operator.
Lists can contain items of any type, including other collections. Here are some
more examples:
(1 2 3 4)
()
(:fred ethel)
(1 2 (a b c) 4 5)
Note that unlike some Lisps, the empty list in Clojure, written as (), isn’t the same as
nil.
2.2.2
Vectors
Like lists, vectors store a series of values. There are several differences described in
section 5.4, but for now only two are important. First, vectors have a literal syntax
using square brackets:
[1 2 :a :b :c]
The other important difference is that when evaluated, vectors simply evaluate each
item in order. No function or macro call is performed on the vector itself, though if a
list appears within the vector, that list is evaluated following the normal rules for a list.
Like lists, vectors are type heterogeneous, and as you might guess, the empty vector []
isn’t the same as nil.
Download from Wow! eBook <www.wowebook.com>
Making things happen: functions
25
2.2.3
Maps
Maps store unique keys and one value per key—similar to what some languages and
libraries call dictionaries or hashes. Clojure actually has several types of maps with differ-
ent properties, but don’t worry about that for now. Maps can be written using a literal
syntax with alternating keys and values inside curly braces. Commas are frequently
used between pairs, but are just whitespace like they are everywhere else in Clojure:
{1 "one", 2 "two", 3 "three"}
Like vectors, every item in a map literal (each key and each value) is evaluated before
the result is stored in the map. Unlike vectors, the order in which they’re evaluated
isn’t guaranteed. Maps can have items of any type for both keys and values, and the
empty map {} isn’t the same as nil.
2.2.4
Sets
Sets are probably the least common collection type that has a literal syntax. Sets store
zero or more unique items. They’re written using curly braces with a leading hash:
#{1 2 "three" :four 0x5}
Again, the empty set #{} isn’t the same as nil.
That’s all for now regarding the basic collection types, but chapter 4 will cover in-
depth the idiomatic uses of each, including their relative strengths and weaknesses.
2.3
Making things happen: functions
Functions in Clojure are a first-class type, meaning that they can be used the same as
any value. Functions can be stored in Vars, held in lists and other collection types, and
passed as arguments to and even returned as the result of other functions.
2.3.1
Calling functions
Clojure borrows its function calling conventions from Lisp, also known as prefix notation:
(+ 1 2 3)
;=> 6
The immediately obvious advantage of prefix over infix notation used by C-style lan-
guages4 is that the former allows any number of operands per operator, whereas infix
allows only two. Another, less obvious advantage to structuring code as prefix notation
is that it completely eliminates the problem of operator precedence. Clojure makes
no distinction between operator notation and regular function calls—all Clojure con-
structs, functions, macros, and operators are formed using prefix, or fully parenthe-
sized, notation. This uniform structure forms the basis for the incredible flexibility
that Lisp-like languages provide.
4 Of course, Java uses infix notation in only a few instances. The remainder of the language forms tend toward