Table Of ContentIN ACTION
SECOND EDITION
Amit Rathore
Francis Avila
M A N N I N G
Praise for the First Edition
“An easy-to-read book and a great way to get up to speed with Clojure.”
—Craig Smith, Suncorp
“A broad but thorough overview of the current state of the art in this exciting new
language.”
—Tim Moore, Atlassian
“Down-to-earth and thorough, just what you need to get building real-world applications.”
—Stuart Caborn, BNP Paribas
“I love the inclusion of testing and web topics!”
—Chris Bailey, HotelTonight
“An insightful look at Clojure and its unique position in the JVM family of languages.
A good read for anyone trying to ‘get’ Clojure.”
—Jason Rogers, MSCI Inc.
“Don't just learn Clojure—learn how to build things with it.”
—Baishampayan Ghose (BG), Qotd, Inc.
“Explains functional programming with Java.”
—Doug Warren, Java Web Services
“It shows what you can get mixing the power of Java libraries with a pragmatic func-
tional language.”
—Federico Tomassetti, Politecnico di Torino
“A very approachable text and a great introduction to Clojure and Lisp.”
—Kevin Butler, HandyApp, LLC
“Brings together the features of Clojure and shows how they can be used cohesively to
implement a number of engineering solutions. Each solution is stunningly simple and
elegant. I highly recommend this book.”
—A.B., Amazon reviewer
Clojure in Action
Second Edition
AMIT RATHORE
FRANCIS AVILA
MANNING
SHELTER ISLAND
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.
20 Baldwin Road
PO Box 761
Shelter Island, NY 11964
Email: orders@manning.com
©2016 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: Karen Miller
20 Baldwin Road Technical development editors: Andrew Luly, Michael Williams
PO Box 761 Copyeditor: Jodie Allen
Shelter Island, NY 11964 Proofreader: Linda Recktenwald
Technical proofreader: Joe Smith
Typesetter: Dennis Dalinnik
Cover designer: Marija Tudor
ISBN: 9781617291524
Printed in the United States of America
1 2 3 4 5 6 7 8 9 10 – EBM – 20 19 18 17 16 15
contents
preface to the second edition xi
preface to the first edition xiii
acknowledgments xvi
about this book xviii
1 Introducing Clojure 1
1.1 Clojure: What and why? 1
Clojure: A modern Lisp 2 ■ Clojure: Pragmatic functional
programming 3 ■ Clojure on the JVM 6
1.2 Language basics 7
Lisp syntax 7 ■ Parentheses 9
1.3 Host interoperation: A JVM crash course 10
Java types, classes, and objects 11 ■ The dot and new
operators 12 ■ Threads and concurrency 13
1.4 Summary 14
v
vi CONTENTS
2 Clojure elements: Data structures and functions 16
2.1 Coding at the REPL 16
Clojure REPL 17 ■ “Hello, world!” 19 ■ Looking up
documentation using doc, find-doc, and apropos 20
A few more points on Clojure syntax 21
2.2 Clojure data structures 24
nil, truth, and falsehood 24 ■ Characters and strings 24
Clojure numbers 25 ■ Symbols and keywords 26
Lists 27 ■ Vectors 29 ■ Maps 31 ■ Sequences 33
2.3 Program structure 34
Functions 34 ■ The let form 35 ■ Side effects with do 37
Reader macros 38
2.4 Program flow 39
Conditionals 39 ■ Logical functions 41 ■ Functional
iteration 44 ■ Threading macros 50
2.5 Summary 54
3 Building blocks of Clojure 55
3.1 Metadata 56
Java type hints 58 ■ Java primitive and array types 59
3.2 Java exceptions: try and throw 60
3.3 Functions 62
Defining functions 62 ■ Calling functions 69
Higher-order functions 70 ■ Writing higher-order functions 73
Anonymous functions 76 ■ Keywords and symbols 77
3.4 Scope 80
Vars and binding 80 ■ The let form revisited 85
Lexical closures 86
3.5 Namespaces 87
ns macro 87 ■ Working with namespaces 90
3.6 Destructuring 91
Vector bindings 91 ■ Map bindings 93
3.7 Reader literals 95
3.8 Summary 97
CONTENTS vii
4 Multimethod polymorphism 98
4.1 Polymorphism and its types 98
Parametric polymorphism 99 ■ Ad hoc polymorphism 99
Subtype polymorphism 101
4.2 Polymorphism using multimethods 103
Life without multimethods 103 ■ Ad hoc polymorphism
using multimethods 103 ■ Multiple dispatch 106
Subtype polymorphism using multimethods 108
4.3 Summary 114
5 Exploring Clojure and Java interop 116
5.1 Calling Java from Clojure 117
Importing Java classes into Clojure 117 ■ Creating
instances 118 ■ Accessing methods and fields 119
Macros and the dot special form 120 ■ Helpful Clojure
macros for working with Java 122 ■ Implementing interfaces
and extending classes 125
5.2 Compiling Clojure code to Java bytecode 126
Example: A tale of two calculators 126 ■ Creating Java classes
and interfaces using gen-class and gen-interface 129
5.3 Calling Clojure from Java 133
5.4 Summary 134
6 State and the concurrent world 135
6.1 The problem with state 136
Common problems with shared state 136
Traditional solution 137
6.2 Separating identities and values 139
Immutable values 140 ■ Objects and time 140
Immutability and concurrency 142
6.3 Clojure’s way 143
Immutability and performance 143 ■ Managed references 144
6.4 Refs 145
Creating refs 145 ■ Mutating refs 145 ■ Software
transactional memory 148
6.5 Agents 150
Creating agents 150 ■ Mutating agents 151 ■ Working with
agents 152 ■ Side effects in STM transactions 155
viii CONTENTS
6.6 Atoms 155
Creating atoms 155 ■ Mutating atoms 156
6.7 Vars 157
Creating vars and root bindings 157 ■ Var bindings 158
6.8 State and its unified access model 159
Creating 159 ■ Reading 159 ■ Mutation 159
Transactions 160 ■ Watching for mutation 160
6.9 Deciding which reference type to use 161
6.10 Futures and promises 162
Futures 162 ■ Promises 163
6.11 Summary 164
7 Evolving Clojure through macros 166
7.1 Macro basics 167
Textual substitution 167 ■ The unless example 168
Macro templates 171 ■ Recap: Why macros? 176
7.2 Macros from within Clojure 177
comment 177 ■ declare 177 ■ defonce 178
and 178 ■ time 179
7.3 Writing your own macros 180
infix 180 ■ randomly 180 ■ defwebmethod 181
defnn 183 ■ assert-true 184
7.4 Summary 185
8 More on functional programming 186
8.1 Using higher-order functions 187
Collecting results of functions 187 ■ Reducing lists of
things 189 ■ Filtering lists of things 191
8.2 Partial application 192
Adapting functions 193 ■ Defining functions 196
8.3 Closures 197
Free variables and closures 197 ■ Delayed computation
and closures 198 ■ Closures and objects 199
An object system for Clojure 202
8.4 Summary 215
CONTENTS ix
9 Protocols, records, and types 217
9.1 The expression problem 218
Setting up the example scenario 218 ■ A closer look at the
expression problem and some potential solutions 222
Clojure’s multimethods solution 223
9.2 Examining the operations side of the expression
problem 225
def-modus-operandi 225 ■ detail-modus-operandi 226
Tracking your modus operandi 227 ■ Error handling and
trouble spots in this solution 233
9.3 Examining the data types side of the expression problem
with protocols 234
defprotocol and extend-protocol 234 ■ Defining data types
with deftype, defrecord, and reify 239
9.4 Summary 245
10 Test-driven development and more 247
10.1 Getting started with TDD: Manipulating dates
in strings 248
First assertion 248 ■ month-from and year-from 251
as-string 252 ■ Incrementing and decrementing 253
Refactor mercilessly 255
10.2 Improving tests through mocking and stubbing 256
Example: Expense finders 256 ■ Stubbing 257
Mocking 260 ■ Mocks versus stubs 261
Managing stubbing and mocking state 264
10.3 Organizing tests 265
The testing macro 266 ■ The are macro 266
10.4 Summary 267
11 More macros and DSLs 268
11.1 A quick review of macros 269
11.2 Anaphoric macros 270
The anaphoric if 270 ■ The thread-it macro 273
11.3 Shifting computation to compile time 276
Example: Rotation ciphers without macros 276
Making the compiler work harder 279