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

Clojure philosophy 3

2

Drinking from the Clojure firehose 20

3

Dipping our toes in the pool 43

PART 2 DATA TYPES . .......................................................................59

4 ■

On scalars 61

5 ■

Composite data types 76

PART 3 FUNCTIONAL PROGRAMMING............................................. 105

6 ■

Being lazy and set in your ways 107

7 ■

Functional programming 125

PART 4 LARGE-SCALE DESIGN ........................................................ 155

8

Macros 157

9

Combining data and code 177

10

Java.next 207

11

Mutation 234

PART 5 TANGENTIAL CONSIDERATIONS.......................................... 275

12 ■

Performance 277

13 ■

Clojure changes the way you think 292

vii

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

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

contents

foreword xvii

preface xix

acknowledgments xxi

about this book xxiii

PART 1 FOUNDATIONS .....................................................1

1 Clojure philosophy 3

1.1 The Clojure way 4

Simplicity 4 Freedom to focus 5 Empowerment 5

Clarity 6 Consistency 7

1.2 Why a(nother) Lisp? 8

Beauty 9 Extreme flexibility 9 Code is data 11

1.3 Functional programming 12

A workable definition of functional programming 12

The implications of functional programming 12

1.4 Why Clojure isn’t especially object-oriented 13

Defining terms 13 Imperative “baked in” 14 Most of what

OOP gives you, Clojure provides 15

1.5 Summary 19

ix

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

x

CONTENTS

2 Drinking from the Clojure firehose 20

2.1 Scalars 21

Numbers 21 Integers 22 Floating-point numbers 22

Rationals 22 Symbols 23 Keywords 23 Strings 23

Characters 23

2.2 Putting things together: collections 24

Lists 24 Vectors 24 Maps 25 Sets 25

2.3 Making things happen: functions 25

Calling functions 25 Defining functions 26 Simplifying

function definitions with def and defn 27 In-place functions

with #() 28

2.4 Vars 28

Declaring bindings using def 28

2.5 Locals, loops, and blocks 29

Blocks 29 Locals 29 Loops 30

2.6 Preventing things from happening: quoting 32

Evaluation 32 Quoting 33 Unquote 34

Unquote-splicing 35 Auto-gensym 36

2.7 Leveraging Java via interop 36

Accessing static class members 36 Creating Java class

instances 36 Accessing Java instance members with the .

operator 37 Setting Java instance properties 37

The .. macro 37 The doto macro 38 Defining classes 38

2.8 Exceptional circumstances 38

A little pitch and catch 38

2.9 Namespaces 39

Creating namespaces using ns 39 Loading other namespaces

with :require 40 Loading and creating mappings with :use 40

Creating mappings with :refer 41 Loading Java classes with

:import 42

2.10 Summary 42

3 Dipping our toes in the pool 43

3.1 Truthiness 44

What’s truth? 44 Don’t create Boolean objects 44

nil versus false 45

3.2 Nil pun with care 45

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

CONTENTS

xi

3.3 Destructuring 47

Your assignment, should you choose to accept it 47

Destructuring with a vector 47 Destructuring with a map 49

Destructuring in function parameters 50 Destructuring versus

accessor methods 50

3.4 Using the REPL to experiment 51

Experimenting with seqs 51 Experimenting with graphics 52

Putting it all together 54 When things go wrong 54

Just for fun 56

3.5 Summary 56

PART 2 DATA TYPES .......................................................59

4 On scalars 61

4.1 Understanding precision 62

Truncation 62 Promotion 63 Overflow 64

Underflow 64 Rounding errors 64

4.2 Trying to be rational 65

Why be rational? 66 How to be rational 66 Caveats of

rationality 67

4.3 When to use keywords 68

How are keywords different from symbols? 68 Qualifying your

keywords 69

4.4 Symbolic resolution 70

Metadata 71 Symbols and namespaces 71 Lisp-1 72

4.5 Regular expressions—the second problem 73

Syntax 73 Functions 74 Beware of mutable matchers 75

4.6 Summary 75

5 Composite data types 76

5.1 Persistence, sequences, and complexity 77

“You keep using that word. I do not think it means what you think it

means.” 77 Sequence terms and what they mean 78

Big-O 81

5.2 Vectors: creating and using them in all their varieties 82

Building vectors 82 Large vectors 83 Vectors as stacks 86

Using vectors instead of reverse 87 Subvectors 88 Vectors as

MapEntries 88 What vectors aren’t 89

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

aren’t 91

5.4 How to use persistent queues 91

A queue about nothing 92 Putting things on 92 Getting

things 93 Taking things off 93

5.5 Persistent sets 94

Basic properties of Clojure sets 94 Keeping your sets in order with

sorted-set 94 contains? 95 clojure.set 96

5.6 Thinking in maps 97

Hash maps 97 Keeping your keys in order with sorted maps 99

Keeping your insertions in order with array maps 100

5.7 Putting it all together: finding the position of items 

in a sequence 101

Implementation 101

5.8 Summary 103

PART 3 FUNCTIONAL PROGRAMMING . ...........................105

6 Being lazy and set in your ways 107

6.1 On immutability 107

Defining immutability 108 Being set in your ways—

immutability 109

6.2 Designing a persistent toy 110

6.3 Laziness 113

Familiar laziness with logical-and 113 Understanding the lazy-

seq recipe 115 Losing your head 117 Employing infinite

sequences 118 The delay and force macros 119

6.4 Putting it all together: a lazy quicksort 121

6.5 Summary 124

7 Functional programming 125

7.1 Functions in all their forms 126

First-class functions 126 Higher-order functions 129

Pure functions 131 Named arguments 132 Constraining

functions with pre- and postconditions 133

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

CONTENTS

xiii

7.2 Closures 135

7.3 Thinking recursively 141

Mundane recursion 142 Tail calls and recur 143 Don’t

forget your trampoline 146 Continuation-passing style 148

7.4 Putting it all together: A* pathfinding 149

The A* implementation 151 Notes about the A*

implementation 154

7.5 Summary 154

PART 4 LARGE-SCALE DESIGN. .......................................155

8 Macros 157

8.1

Data is code is data 158

Syntax-quote, unquote, and splicing 160 Macro rules of

thumb 161

8.2 Defining control structures 161

Defining control structures without syntax-quote 162

Defining control structures using syntax-quote and unquoting 163

8.3 Macros combining forms 164

8.4 Using macros to change forms 165

8.5 Using macros to control symbolic resolution time 169

Anaphora 170 (Arguably) useful selective name

capturing 171

8.6

Using macros to manage resources 171

8.7

Putting it all together: macros returning functions 173

8.8

Summary 176

9 Combining data and code 177

9.1 Namespaces 178

Creating namespaces 179 Expose only what’s needed 180

Declarative inclusions and exclusions 182

9.2 Exploring Clojure multimethods with the Universal

Design Pattern 183

The parts 184 Usage 185 Multimethods to the rescue 185

Ad hoc hierarchies for inherited behaviors 186 Resolving conflict

in hierarchies 187 Arbitrary dispatch for true maximum

power 188

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

base with deftype 200

9.4 Putting it all together: a fluent builder for chess moves 202

Java implementation 202 Clojure implementation 204

9.5 Summary 206

10 Java.next 207

10.1

Generating objects on the fly with proxy 208

A simple dynamic web service 209

10.2 Clojure gen-class and GUI programming 212

Namespaces as class specifications 212 Exploring user interface

design and development with Clojure 215

10.3 Clojure’s relationship to Java arrays 218

Types of arrays: primitive and reference 218 Array mutability 220

That unfortunate naming convention 221 Multidimensional

arrays 222 Variadic method/constructor calls 222

10.4 All Clojure functions implement... 222

java.util.Comparator 223 java.lang.Runnable 223

java.util.concurrent.Callable 224

10.5 Using Clojure data structures in Java APIs 224

java.util.List 225 java.lang.Comparable 225

java.util.RandomAccess 226 java.util.Collection 226

java.util.Set 227

10.6 definterface 227

Generating interfaces on the fly 227

10.7 Be wary of exceptions 229

A bit of background regarding exceptions 230 Runtime versus

compile-time exceptions 230 Handling exceptions 232

Custom exceptions 233

10.8 Summary 233

11 Mutation 234

11.1

Software transactional memory with multiversion

concurrency control and snapshot isolation 235

Transactions 236 Embedded transactions 236 The things

that STM makes easy 237 Potential downsides 238

The things that make STM unhappy 239

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

CONTENTS

xv

11.2 When to use Refs 240

Coordinated, synchronous change using alter 241 Commutative

change with commute 244 Vulgar change with ref-set 245

Fixing write-skew with ensure 245 Refs under stress 246

11.3 When to use Agents 247

In-process versus distributed concurrency models 248

Controlling I/O with an Agent 249 The difference between send

and send-off 251 Error handling 252 When not to use

Agents 254

11.4 When to use Atoms 255

Sharing across threads 255 Using Atoms in transactions 256

11.5 When to use locks 258

Safe mutation through locking 259 Using Java’s explicit

locks 260

11.6 When to use futures 261

Futures as callbacks 262

11.7 When to use promises 265

Parallel tasks with promises 265 Callback API to blocking

API 266 Deterministic deadlocks 267

11.8 Parallelism 268

pvalues 268 pmap 269 pcalls 269

11.9 Vars and dynamic binding 270

The binding macro 271 Creating a named Var 271

Creating anonymous Vars 272 Dynamic scope 273

11.10 Summary 274

PART 5 TANGENTIAL CONSIDERATIONS . ....................... 275

12 Performance 277

12.1

Type hints 278

Advantages of type adornment 278 Type-hinting arguments

and returns 278 Type-hinting objects 280

12.2 Transients 280

Ephemeral garbage 280 Transients compare in efficiency to

mutable collections 281

12.3 Chunked sequences 282

Regaining one-at-a-time laziness 283

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

xvi

CONTENTS

12.4 Memoization 284

Re-examining memoization 285 A memoization protocol 285

12.5 Understanding coercion 287

First rule of coercion: don’t 288 Corollary: you’re probably not

doing it right 288 Second rule of coercion: don’t 290

Third rule of coercion: coerce a stable local 290 Fourth rule of

coercion: watch your sizes 290 Fifth rule of coercion: truncate

only as a goal 290

12.6 Summary 291

13 Clojure changes the way you think 292

13.1 DSLs 293

A ubiquitous DSL 293 Putting parentheses around the

specification 294 A note about Clojure’s approach to

DSLs 298

13.2 Testing 298

Some useful techniques 299 Contracts programming 301

13.3 A lack of design patterns 303

Clojure’s first-class design patterns 303

13.4 Error handling and debugging 306

Error handling 306 Debugging 308

13.5

Fare thee well 312

resources 313

index 319

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

GOOGLE

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