You are previewing Clojure Programming.

Clojure Programming

Cover of Clojure Programming by Chas Emerick... Published by O'Reilly Media, Inc.
  1. Clojure Programming
  2. SPECIAL OFFER: Upgrade this ebook with O’Reilly
  3. Preface
    1. Who Is This Book For?
      1. Engaged Java Developers
      2. Ruby, Python, and Other Developers
    2. How to Read This Book
      1. Start with Practical Applications of Clojure
      2. Start from the Ground Up with Clojure’s Foundational Concepts
    3. Who’s “We”?
      1. Chas Emerick
      2. Brian Carper
      3. Christophe Grand
    4. Acknowledgments
      1. And Last, but Certainly Far from Least
    5. Conventions Used in This Book
    6. Using Code Examples
    7. Safari® Books Online
    8. How to Contact Us
  4. 1. Down the Rabbit Hole
    1. Why Clojure?
    2. Obtaining Clojure
    3. The Clojure REPL
    4. No, Parentheses Actually Won’t Make You Go Blind
    5. Expressions, Operators, Syntax, and Precedence
    6. Homoiconicity
    7. The Reader
      1. Scalar Literals
      3. Whitespace and Commas
      4. Collection Literals
      5. Miscellaneous Reader Sugar
    8. Namespaces
    9. Symbol Evaluation
    10. Special Forms
      1. Suppressing Evaluation: quote
      2. Code Blocks: do
      3. Defining Vars: def
      4. Local Bindings: let
      5. Destructuring (let, Part 2)
      6. Creating Functions: fn
      7. Conditionals: if
      8. Looping: loop and recur
      9. Referring to Vars: var
      10. Java Interop: . and new
      11. Exception Handling: try and throw
      12. Specialized Mutation: set!
      13. Primitive Locking: monitor-enter and monitor-exit
    11. Putting It All Together
      1. eval
    12. This Is Just the Beginning
  5. I. Functional Programming and Concurrency
    1. 2. Functional Programming
      1. What Does Functional Programming Mean?
      2. On the Importance of Values
      3. First-Class and Higher-Order Functions
      4. Composition of Function(ality)
      5. Pure Functions
      6. Functional Programming in the Real World
    2. 3. Collections and Data Structures
      1. Abstractions over Implementations
      2. Concise Collection Access
      3. Data Structure Types
      4. Immutability and Persistence
      5. Metadata
      6. Putting Clojure’s Collections to Work
      7. In Summary
    3. 4. Concurrency and Parallelism
      1. Shifting Computation Through Time and Space
      2. Parallelism on the Cheap
      3. State and Identity
      4. Clojure Reference Types
      5. Classifying Concurrent Operations
      6. Atoms
      7. Notifications and Constraints
      8. Refs
      9. Vars
      10. Agents
      11. Using Java’s Concurrency Primitives
      12. Final Thoughts
  6. II. Building Abstractions
    1. 5. Macros
      1. What Is a Macro?
      2. Writing Your First Macro
      3. Debugging Macros
      4. Syntax
      5. When to Use Macros
      6. Hygiene
      7. Common Macro Idioms and Patterns
      8. The Implicit Arguments: &env and &form
      9. In Detail: -> and ->>
      10. Final Thoughts
    2. 6. Datatypes and Protocols
      1. Protocols
      2. Extending to Existing Types
      3. Defining Your Own Types
      4. Implementing Protocols
      5. Protocol Introspection
      6. Protocol Dispatch Edge Cases
      7. Participating in Clojure’s Collection Abstractions
      8. Final Thoughts
    3. 7. Multimethods
      1. Multimethods Basics
      2. Toward Hierarchies
      3. Hierarchies
      4. Making It Really Multiple!
      5. A Few More Things
      6. Final Thoughts
  7. III. Tools, Platform, and Projects
    1. 8. Organizing and Building Clojure Projects
      1. Project Geography
      2. Build
      3. Final Thoughts
    2. 9. Java and JVM Interoperability
      1. The JVM Is Clojure’s Foundation
      2. Using Java Classes, Methods, and Fields
      3. Handy Interop Utilities
      4. Exceptions and Error Handling
      5. Type Hinting for Performance
      6. Arrays
      7. Defining Classes and Implementing Interfaces
      8. Using Clojure from Java
      9. Collaborating Partners
    3. 10. REPL-Oriented Programming
      1. Interactive Development
      2. Tooling
      3. Debugging, Monitoring, and Patching Production in the REPL
      4. Limitations to Redefining Constructs
      5. In Summary
  8. IV. Practicums
    1. 11. Numerics and Mathematics
      1. Clojure Numerics
      2. Clojure Mathematics
      3. Equality and Equivalence
      4. Optimizing Numeric Performance
      5. Visualizing the Mandelbrot Set in Clojure
    2. 12. Design Patterns
      1. Dependency Injection
      2. Strategy Pattern
      3. Chain of Responsibility
      4. Aspect-Oriented Programming
      5. Final Thoughts
    3. 13. Testing
      1. Immutable Values and Pure Functions
      2. clojure.test
      3. Growing an HTML DSL
      4. Relying upon Assertions
    4. 14. Using Relational Databases
      2. Korma
      3. Hibernate
      4. Final Thoughts
    5. 15. Using Nonrelational Databases
      1. Getting Set Up with CouchDB and Clutch
      2. Basic CRUD Operations
      4. _changes: Abusing CouchDB as a Message Queue
      5. À la Carte Message Queues
      6. Final Thoughts
    6. 16. Clojure and the Web
      1. The “Clojure Stack”
      2. The Foundation: Ring
      3. Routing Requests with Compojure
      4. Templating
      5. Final Thoughts
    7. 17. Deploying Clojure Web Applications
      1. Java and Clojure Web Architecture
      2. Running Web Apps Locally
      3. Web Application Deployment
      4. Going Beyond Simple Web Application Deployment
  9. V. Miscellanea
    1. 18. Choosing Clojure Type Definition Forms Wisely
    2. 19. Introducing Clojure into Your Workplace
      1. Just the Facts…
      2. Emphasize Productivity
      3. Emphasize Community
      4. Be Prudent
    3. 20. What’s Next?
      1. (dissoc Clojure 'JVM)
      2. 4Clojure
      3. Overtone
      4. core.logic
      5. Pallet
      6. Avout
      7. Clojure on Heroku
  10. Index
  11. About the Authors
  12. Colophon
  13. SPECIAL OFFER: Upgrade this ebook with O’Reilly
O'Reilly logo


At this point, we should understand much of how the nontrivial parts of the Clojure REPL (and therefore Clojure itself) work:

  • Read: the Clojure reader reads the textual representation of code, producing the data structures (e.g., lists, vectors, and so on) and atomic values (e.g., symbols, numbers, strings, etc.) indicated in that code.

  • Evaluate: many of the values emitted by the reader evaluate to themselves (including most data structures and scalars like strings and keywords). We explored earlier in Expressions, Operators, Syntax, and Precedence how lists evaluate to calls to the operator in function position.

The only thing left to understand about evaluation now is how symbols are evaluated. So far, we’ve used them to both name and refer to functions, locals, and so on. Outside of identifying locals, the semantics of symbol evaluation are tied up with namespaces, Clojure’s fundamental unit of code modularity.

All Clojure code is defined and evaluated within a namespace. Namespaces are roughly analogous to modules in Ruby or Python, or packages in Java.[14] Fundamentally, they are dynamic mappings between symbols and either vars or imported Java classes.

One of Clojure’s reference types,[15] vars are mutable storage locations that can hold any value. Within the namespace where they are defined, vars are associated with a symbol that other code can use to look up the var, and therefore the value it holds.

Vars are defined in Clojure using the def special form, which only ever acts within the current namespace.[16] Let’s define a var now in the user namespace, named x; the name of the var is the symbol that it is keyed under within the current namespace:

(def x 1)
;= #'user/x

We can access the var’s value using that symbol:

;= 1

The symbol x here is unqualified, so is resolved within the current namespace. We can also redefine vars; this is critical for supporting interactive development at the REPL:

(def x "hello")
;= #'user/x
;= "hello"

Vars are not variables

Vars should only ever be defined in an interactive context—such as a REPL—or within a Clojure source file as a way of defining named functions, other constant values, and the like. In particular, top-level vars (that is, globally accessible vars mapped within namespaces, as defined by def and its variants) should only ever be defined by top-level expressions, never in the bodies of functions in the normal course of operation of a Clojure program.

See Vars Are Not Variables for further elaboration.

Symbols may also be namespace-qualified, in which case they are resolved within the specified namespace instead of the current one:

*ns*                 1
;= #<Namespace user>
(ns foo)
;= nil
;= #<Namespace foo>
;= "hello"
;= #<CompilerException java.lang.RuntimeException:
;=   Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0)>

The current namespace is always bound to *ns*.

Here we created a new namespace using the ns macro (which has the side effect of switching us to that new namespace in our REPL), and then referred to the value of x in the user namespace by using the namespace-qualified symbol user/x. Since we only just created this new namespace foo, it doesn’t have a mapping for the x symbol, so attempting to resolve it fails.


You need to know how to create, define, organize, and manipulate namespaces in order to use Clojure effectively. There is a whole suite of functions for this; please refer to Defining and Using Namespaces for our guidelines in their use.

We mentioned earlier that namespaces also map between symbols and imported Java classes. All classes in the java.lang package are imported by default into each Clojure namespace, and so can be referred to without package qualification; to refer to un-imported classes, a package-qualified symbol must be used. Any symbol that names a class evaluates to that class:

;= java.lang.String
;= java.lang.Integer
;= java.util.List

In addition, namespaces by default alias all of the vars defined in the primary namespace of Clojure’s standard library, clojure.core. For example, there is a filter function defined in clojure.core, which we can access without namespace-qualifying our reference to it:

;= #<core$filter clojure.core$filter@7444f787>

These are just the barest basics of how Clojure namespaces work; learn more about them and how they should be used to help you structure your projects in Defining and Using Namespaces.

[14] In fact, namespaces correspond precisely with Java packages when types defined in Clojure are compiled down to Java classes. For example, a Person type defined in the Clojure namespace app.entities will produce a Java class named app.entities.Person. See more about defining types and records in Clojure in Chapter 6.

[15] See Clojure Reference Types for a full discussion of Clojure’s reference types, all of which contribute different capabilities to its concurrency toolbox.

[16] Remember that the Clojure REPL session always starts in the default user namespace.

The best content for your career. Discover unlimited learning on demand for around $1/day.