We wrote this book for you.
We've worked with Clojure for many years now, and have enjoyed using it to build projects, websites, products, and businesses of all kinds. We love the language, and we think you will too.
Clojure is a dynamic, general-purpose programming language that runs on the Java Virtual Machine that offers superior interactive development with the speed and reliable runtime of the JVM. Clojure Programming is our attempt to get you up to speed as efficiently and pleasantly as possible.
To ease your way, we included examples throughout the book to help relate aspects of Clojure to their analogues in Java, Ruby, and Python; these landmarks should help you keep your bearings throughout your new language adventures. Why those languages and not others? First, because nearly all programmers know at least one of them; and second, Clojure has a great deal to offer to Java, Ruby, and Python developers:
Engaged Java developers are usually found working in demanding environments solving nontrivial, often domain-specific problems. For you, you'll find Clojure to be welcome relief. It runs on the JVM with excellent performance characteristics, interoperates with all of your existing libraries, tools, and applications, and is simpler than Java yet remains demonstrably more expressive and more concise.
Ruby and Python developers are usually unwilling to compromise on language expressivity, developer happiness, and the joys of working within a thriving community. Clojure is a natural next step for you. It delivers on these things in spades, but runs on a more capable execution platform with better runtime performance and a larger selection of libraries than those available for either Ruby or Python.
In the end, we hope you find the book as accessible and as thought-provoking as Clojure itself.
If you like, we'll occasionally point you towards other tools, resources, and events that will help you get the most out of the book and Clojure itself, all hand-curated by us.
Follow @ClojureBook on Twitter; or,
Join the Clojure Programming mailing list:
News, events, goodies
Read the first chapter free- May 1, 2012: Free Starting Clojure webcast with Chas Emerick
- May 14-16, 2012: Clojure training with Christophe Grand
- May 24-25, 2012: Join Christophe Grand and Chas Emerick at EuroClojure 2012
- Get the latest Clojure Atlas for just $5 with your copy of Clojure Programming
Examples and Sample Code
All of the code from the book (including sample projects, inline REPL interactions, etc) is available for browsing, download, cloning, and so on from Github. We will continue to keep that repository alive, so that the code therein is up to date, compatible with any future releases of Clojure, and so on. And, if you see any problems, please don't hesitate to open an issue.
Table of Contents
- Down the rabbit hole
- Why Clojure?
- Obtaining Clojure
- The Clojure REPL
- No, parentheses actually won’t make you go blind
- Expressions, operators, syntax, and precedence
- Homoiconicity
- The Reader
- Scalar Literals
- Strings
- Booleans
nil- Characters
- Keywords
- Symbols
- Numbers
- Regular Expressions
- Comments
- Whitespace and Commas
- Collection Literals
- Miscellaneous reader sugar
- Scalar Literals
- Namespaces
- Symbol evaluation
- Special Forms
- Suppressing evaluation:
quote - Code blocks:
do - Defining vars:
def - Local bindings:
let - Destructuring (
let, part 2)- Sequential destructuring
- Map destructuring
- Creating functions:
fn- Destructuring function arguments
- Function literals
- Conditionals:
if - Looping:
loopandrecur - Referring to vars:
var - Java interop:
.andnew - Exception handling:
tryandthrow - Specialized mutation:
set! - Primitive locking:
monitor-enterandmonitor-exit
- Suppressing evaluation:
- Putting it all together
eval
- This is just the beginning
- Functional programming
- What does functional programming mean?
- On the importance of values
- About values
- Comparing values to mutable objects
- A critical choice
- First class and higher-order functions
applying ourselvespartially
- Composition of Function(ality)
- Writing higher order functions
- Building a primitive logging system with composable higher-order functions
- Pure functions
- Why are pure functions interesting?
- Functional programming in the real world
- Collections and data structures
- Abstractions over implementations
- Collection
- Sequences
- Sequences are not iterators
- Sequences are not lists
- Creating seqs
- Lazy seqs
- Head retention
- Associative
- Beware of
nilvalues
- Beware of
- Indexed
- Stack
- Set
- Sorted
- Comparators and predicates to define ordering
- Concise collection access
- Idiomatic usage
- Collections and keys and higher-order functions
- Data structure types
- Lists
- Vectors
- Vectors as tuples
- Sets
- Maps
- Maps as ad-hoc structs
- Other usages of maps
- Immutability and persistence
- Persistence and structural sharing
- Visualizing persistence: Lists
- Visualizing persistence: Maps (and vectors, and sets)
- Tangible benefits
- Transients
- Persistence and structural sharing
- Metadata
- Putting Clojure’s collections to work
- Identifiers and cycles
- Thinking different: from imperative to functional
- Revisiting a classic: Conway’s Game of Life
- Maze generation
- Navigation, update and zippers
- Manipulating zippers
- Custom zippers
- Ariadne’s zipper
- In summary
- Getting rid of ids: compiling regexes
- Abstractions over implementations
- Concurrency and parallelism
- Shifting computation through time and space
- Delays
- Futures
- Promises
- Parallelism on the cheap
- State and Identity
- Clojure reference types
- Classifying concurrent operations
- Atoms
- Notifications and constraints
- Watches
- Validators
- Refs
- Software transactional memory
- The mechanics of ref change
- Understanding
alter - Minimizing transaction conflict with
commute - Clobbering ref state with
ref-set - Enforcing local consistency using validators
- Understanding
- The sharp corners of software transactional memory
- Side-effecting functions strictly verboten
- Minimize the scope of each transaction
- Readers may retry
- Write skew
- Vars
- Defining vars
- Private vars
- Docstrings
- Constants
- Dynamic scope
- Vars are not “variables”
- Forward declarations
- Defining vars
- Agents
- Dealing with errors in agent actions
- Agent error handlers and modes
- I/O, transactions, and nested sends
- Persisting reference states with an agent-based write-behind log
- Using agents to parallelize workloads
- Dealing with errors in agent actions
- Using Java’s concurrency primitives
locking
- Final thoughts
- Shifting computation through time and space
- Macros
- What is a macro?
- What macros are not
- What can macros do that functions cannot?
- Macros vs. Ruby
eval
- Writing our first macro
- Debugging macros
- Macroexpansion
- Syntax
quotevs.syntax-quoteunquoteandunquote-splicing
- When to Use Macros
- Hygiene
- Gensyms to the rescue
- Letting the user pick names
- Double-evaluation
- Common macro idioms and patterns
- The implicit arguments:
&envand&form&env&form- Producing useful macro error messages
- Preserving user-provided type hints
- Testing contextual macros
- In detail:
->and->> - Final thoughts
- What is a macro?
- Datatypes & protocols
- Protocols
- Extending to existing types
- Defining your own types
- Records
- Constructors and factory functions
- When to use maps or records?
- Types
- Records
- Implementing protocols
- Inline implementation
- Inline implementations of Java interfaces
- Defining anonymous types with
reify
- Reusing implementations
- Inline implementation
- Protocol introspection
- Protocol dispatch edge cases
- Participating in Clojure’s collection abstractions
- Final thoughts
- Multimethods
- Multimethods basics
- Towards hierarchies
- Hierarchies
- Independent hierarchies
- Making it really multiple!
- A few more things
- Multiple inheritance
- Introspecting multimethods
typevsclass; or, the revenge of the map- The range of dispatch functions is unlimited
- Final thoughts
- Organizing and building Clojure projects
- Project geography
- Defining and using namespaces
- Namespaces and files
- A classpath primer
- Location, location, location
- The functional organization of Clojure codebases
- Some “very general principles”
- Defining and using namespaces
- Build
- Ahead-of-time compilation
- Dependency Management
- The Maven dependency management model
- Artifacts and coordinates
- Repositories
- Dependencies
- Build tools & configuration patterns
-
- Maven
- Leiningen
- AOT compilation configuration
- Building mixed-source projects
- Final thoughts
- Project geography
- Java and JVM interoperability
- The JVM is Clojure’s Foundation
- Using Java Classes, Methods, and Fields
- Handy Interop Utilities
- Exceptions and Error Handling
- Escaping checked exceptions
with-open,finally‘s lament
- Type Hinting for Performance
- Arrays
- Defining classes and implementing interfaces
- Instances of anonymous classes:
proxy - Defining named classes
gen-class
- Annotations
- Producing annotated JUnit tests
- Implementing JAX-RS web service endpoints
- Instances of anonymous classes:
- Using Clojure from Java
- Using
deftypeanddefrecordclasses - Implementing protocol interfaces
- Using
- Collaborating partners
- REPL-Oriented programming
- Interactive development
- The persistent, evolving environment
- Tooling
- The Bare REPL
- Introspecting namespaces
- Eclipse
- Emacs
clojure-modeandpareditinferior-lisp- SLIME
- The Bare REPL
- Debugging, monitoring, and patching production in the REPL
- Special considerations for “deployed” REPLs
- Limitations to redefining constructs
- In summary
- Interactive development
- Numerics and Mathematics
- Clojure Numerics
- Clojure prefers 64-bit (or larger) representations
- Clojure has a mixed numerics model
- Rationals
- The rules of numeric contagion
- Clojure Mathematics
- Bounded vs. arbitrary precision
- Unchecked ops
- Scale and rounding modes for arbitrary-precision decimals ops
- Equality and equivalence
- Object identity (
identical?) - Reference equality (
*) - Numeric equivalence (
**)- Equivalence can preserve your sanity
- Object identity (
- Optimizing numeric performance
- Declare functions to take and return primitives
- Type errors and warnings
- Use primitive arrays judiciously
- The mechanics of primitive arrays
- Automating type hinting of multidimensional array operations
- Declare functions to take and return primitives
- Visualizing the Mandlebrot Set in Clojure
- Clojure Numerics
- Design patterns
- Dependency Injection
- Strategy Pattern
- Chain of Responsibility
- Aspect-oriented programming
- Final thoughts
- Testing
- Immutable values and pure functions
- Mocking
clojure.test- Defining tests
- Test “suites”
- Fixtures
- Growing an HTML DSL
- Relying upon
assertions- Preconditions and postconditions
- Immutable values and pure functions
- Using relational databases
- clojure.java.jdbc
with-query-resultsexplained- Transactions
- Connection pooling
- Korma
- Prelude
- Queries
- Why bother with a DSL?
- Hibernate
- Setup
- Persisting data
- Running queries
- Removing boilerplate
- Final thoughts
- clojure.java.jdbc
- Using nonrelational databases
- Getting Set Up with CouchDB and Clutch
- Basic CRUD operations
- Views
- A Simple (Javascript) View
- Views in Clojure
_changes: Abusing CouchDB as a message queue- á la carte message queues
- Final Thoughts
- Clojure & The Web
- The “Clojure stack”
- The foundation: Ring
- Requests and responses
- Adapters
- Handlers
- Middleware
- Routing requests with Compojure
- Templating
- Enlive: Selector-Based HTML Transformation
- Testing the waters
- Selectors
- Iterating and branching
- Putting everything together
- Enlive: Selector-Based HTML Transformation
- Final thoughts
- Deploying Clojure web applications
- Java and Clojure web architecture
- Web application packaging
- Building
.warfiles with Maven - Building
.warfiles with Leiningen
- Building
- Web application packaging
- Running webapps locally
- Web application deployment
- Deploying Clojure apps to Amazon’s Elastic Beanstalk
- Going beyond simple web application deployment
- Java and Clojure web architecture
- Choosing Clojure type definition forms wisely
- Introducing Clojure to your workplace
- Just the facts…
- Emphasize productivity
- Emphasize community
- Be prudent
- What’s next?
(dissoc Clojure ‘JVM)- ClojureCLR
- ClojureScript
- 4Clojure
- Overtone
core.logic- Pallet
- Avout
- Clojure on Heroku