You are previewing Practical Clojure.
O'Reilly logo
Practical Clojure

Book Description

This book is the first definitive reference for the Clojure language, providing both an introduction to functional programming in general and a more specific introduction to Clojure's features. This book demonstrates the use of the language through examples, including features such as STM and immutability, which may be new to programmers coming from other languages.

  • Overview of functional programming and description of what sets Clojure apart from other languages

  • Detailed explanation of Clojure's special features

  • Examples of real-world tasks that are well-suited to Clojure's capabilities, starting with simple tasks and moving on to more complex applications

  • Table of Contents

    1. Copyright
    2. About the Authors
    3. About the Technical Reviewer
    4. Acknowledgments
    5. 1. The Clojure Way
      1. 1.1. Clojure's Philosophy and Special Features
        1. 1.1.1. A Next-Generation Language
        2. 1.1.2. Dynamic and Powerful (Yes, It's a Lisp)
        3. 1.1.3. The Java Platform
      2. 1.2. Functional Programming
        1. 1.2.1. Purely Functional Programming
        2. 1.2.2. Clojure's Compromise
        3. 1.2.3. Immutability
        4. 1.2.4. What about Object-Oriented Programming?
          1. 1.2.4.1. Structure of a Clojure Program
        5. 1.2.5. State Management
        6. 1.2.6. State and Identity
        7. 1.2.7. Software Transactional Memory
      3. 1.3. Summary
    6. 2. The Clojure Environment
      1. 2.1. "Hello World" in Clojure
      2. 2.2. Clojure Forms
        1. 2.2.1. Literals
        2. 2.2.2. Symbols
        3. 2.2.3. Composite Forms
        4. 2.2.4. Special Forms
      3. 2.3. Writing and Running Source Files
      4. 2.4. Vars, Namespaces, and the Environment
      5. 2.5. Symbols and Symbol Resolution
        1. 2.5.1. Symbol Names
        2. 2.5.2. Symbol Resolution and Scope
      6. 2.6. Namespaces
        1. 2.6.1. Declaring Namespaces
        2. 2.6.2. Referencing Namespaces
        3. 2.6.3. Structuring Source Files
      7. 2.7. Summary
    7. 3. Controlling Program Flow
      1. 3.1. Functions
        1. 3.1.1. First-Class Functions
        2. 3.1.2. Defining Functions with fn
        3. 3.1.3. Defining Functions with defn
        4. 3.1.4. Functions of Multiple Arities
        5. 3.1.5. Functions with Variable Arguments
        6. 3.1.6. Shorthand Function Declaration
      2. 3.2. Conditional Expressions
      3. 3.3. Local Bindings
      4. 3.4. Looping and Recursion
        1. 3.4.1. Tail Recursion
          1. 3.4.1.1. Clojure'srecur
          2. 3.4.1.2. Using loop
      5. 3.5. Deliberate Side Effects
        1. 3.5.1.
          1. 3.5.1.1. Using do
          2. 3.5.1.2. Side Effects in Function Definitions
      6. 3.6. Functional Programming Techniques
        1. 3.6.1. First-Class Functions
          1. 3.6.1.1. Consuming First-Class Functions
          2. 3.6.1.2. Producing First-Class Functions
        2. 3.6.2. Closures
        3. 3.6.3. Currying and Composing Functions
          1. 3.6.3.1. Using partial to Curry Functions
          2. 3.6.3.2. Using comp to Compose Functions
        4. 3.6.4. Putting It All Together
    8. 4. Data in Clojure
      1. 4.1. How to Represent and Manipulate Data
        1. 4.1.1. Nil
      2. 4.2. Primitive Types
        1. 4.2.1. Numbers
          1. 4.2.1.1. Common Numeric Functions
            1. 4.2.1.1.1. Addition (+)
            2. 4.2.1.1.2. Subtraction (–)
            3. 4.2.1.1.3. Multiplication (*)
            4. 4.2.1.1.4. Division (/)
            5. 4.2.1.1.5. inc
            6. 4.2.1.1.6. dec
            7. 4.2.1.1.7. quot
            8. 4.2.1.1.8. rem
            9. 4.2.1.1.9. min
            10. 4.2.1.1.10. max
            11. 4.2.1.1.11. Equals Function (==)
            12. 4.2.1.1.12. Greater-Than Function (<)
            13. 4.2.1.1.13. Greater-Than-or-Equals Function (<=)
            14. 4.2.1.1.14. Less-Than (>)
            15. 4.2.1.1.15. The Less-Than-or-Equals (>=)
            16. 4.2.1.1.16. zero?
            17. 4.2.1.1.17. pos?
            18. 4.2.1.1.18. neg?
            19. 4.2.1.1.19. number?
        2. 4.2.2. Strings
          1. 4.2.2.1. Common String Functions
            1. 4.2.2.1.1. str
            2. 4.2.2.1.2. subs
            3. 4.2.2.1.3. string?
            4. 4.2.2.1.4. print & println
          2. 4.2.2.2. Regular Expression Functions
            1. 4.2.2.2.1. re-pattern
            2. 4.2.2.2.2. re-matches
            3. 4.2.2.2.3. re-matcher
            4. 4.2.2.2.4. re-find
            5. 4.2.2.2.5. re-groups
            6. 4.2.2.2.6. re-seq
        3. 4.2.3. Boolean
          1. 4.2.3.1. Common Boolean Functions
            1. 4.2.3.1.1. not
            2. 4.2.3.1.2. and
            3. 4.2.3.1.3. or
        4. 4.2.4. Characters
          1. 4.2.4.1. char
        5. 4.2.5. Keywords
          1. 4.2.5.1. keyword
          2. 4.2.5.2. keyword?
      3. 4.3. Collections
        1. 4.3.1. Lists
          1. 4.3.1.1. list
          2. 4.3.1.2. peek
          3. 4.3.1.3. pop
          4. 4.3.1.4. list?
        2. 4.3.2. Vectors
          1. 4.3.2.1. vector
          2. 4.3.2.2. vec
          3. 4.3.2.3. get
          4. 4.3.2.4. peek
          5. 4.3.2.5. vector?
          6. 4.3.2.6. conj
          7. 4.3.2.7. assoc
          8. 4.3.2.8. pop
          9. 4.3.2.9. subvec
        3. 4.3.3. Maps
          1. 4.3.3.1. Struct Maps
          2. 4.3.3.2. Maps As Objects
            1. 4.3.3.2.1. assoc
            2. 4.3.3.2.2. dissoc
            3. 4.3.3.2.3. conj
            4. 4.3.3.2.4. merge
            5. 4.3.3.2.5. merge-with
            6. 4.3.3.2.6. get
            7. 4.3.3.2.7. contains?
            8. 4.3.3.2.8. map?
            9. 4.3.3.2.9. keys
            10. 4.3.3.2.10. vals
        4. 4.3.4. Sets
          1. 4.3.4.1. Common Set Functions
            1. 4.3.4.1.1. clojure.set/union
            2. 4.3.4.1.2. clojure.set/intersection
            3. 4.3.4.1.3. clojure.set/difference
      4. 4.4. Summary
    9. 5. Sequences
      1. 5.1. What Are Sequences?
        1. 5.1.1. Sequenceable Types
      2. 5.2. Anatomy of a Sequence
      3. 5.3. Constructing Sequences
      4. 5.4. Lazy Sequences
        1. 5.4.1. An Example of Laziness
        2. 5.4.2. Constructing Lazy Sequences
          1. 5.4.2.1. Constructing Lazy Sequences Directly
          2. 5.4.2.2. Constructing Lazy Sequences Using Sequence Generator Functions
        3. 5.4.3. Lazy Sequences and Memory Management
      5. 5.5. The Sequence API
        1. 5.5.1. Sequence Creation
          1. 5.5.1.1. seq
          2. 5.5.1.2. vals
          3. 5.5.1.3. keys
          4. 5.5.1.4. rseq
          5. 5.5.1.5. lazy-seq
          6. 5.5.1.6. repeatedly
          7. 5.5.1.7. iterate
          8. 5.5.1.8. repeat
          9. 5.5.1.9. range
          10. 5.5.1.10. distinct
          11. 5.5.1.11. filter
          12. 5.5.1.12. remove
          13. 5.5.1.13. cons
          14. 5.5.1.14. concat
          15. 5.5.1.15. lazy-cat
          16. 5.5.1.16. mapcat
          17. 5.5.1.17. cycle
          18. 5.5.1.18. interleave
          19. 5.5.1.19. interpose
          20. 5.5.1.20. rest
          21. 5.5.1.21. next
          22. 5.5.1.22. drop
          23. 5.5.1.23. drop-while
          24. 5.5.1.24. take
          25. 5.5.1.25. take-nth
          26. 5.5.1.26. take-while
          27. 5.5.1.27. drop-last
          28. 5.5.1.28. reverse
          29. 5.5.1.29. sort
          30. 5.5.1.30. sort-by
          31. 5.5.1.31. split-at
          32. 5.5.1.32. split-with
          33. 5.5.1.33. partition
          34. 5.5.1.34. map
      6. 5.6. Summary
    10. 6. State Management
      1. 6.1. State in an Immutable World
        1. 6.1.1. The Old Way
        2. 6.1.2. State and Identity
        3. 6.1.3. State and Identity in Clojure
          1. 6.1.3.1. Coordinated vs. Independent State
          2. 6.1.3.2. Synchronous vs. Asynchronous Updates
      2. 6.2. Refs and Transactions
        1. 6.2.1. Creating and Accessing refs
        2. 6.2.2. Updating refs
          1. 6.2.2.1. Transactions
          2. 6.2.2.2. Tools for Updating refs
          3. 6.2.2.3. Examples
      3. 6.3. Atoms
        1. 6.3.1. Using Atoms
        2. 6.3.2. When to Use Atoms
      4. 6.4. Asynchronous Agents
        1. 6.4.1. Creating and Updating Agents
          1. 6.4.1.1. Update Semantics
        2. 6.4.2. Errors and Agents
          1. 6.4.2.1. Dealing with Agents in a Failed State
        3. 6.4.3. Waiting for Agents
        4. 6.4.4. Shutting Down Agents
        5. 6.4.5. When to Use Agents
      5. 6.5. Vars and Thread-Local State
        1. 6.5.1. When to Use Thread-Local Vars
      6. 6.6. Keeping Track of Identities
        1. 6.6.1. Validators
        2. 6.6.2. Watches
      7. 6.7. Summary
    11. 7. Namespaces and Libraries
      1. 7.1. Organizing Clojure Code
      2. 7.2. Namespace Basics
        1. 7.2.1. Switching Namespaces with in-ns
        2. 7.2.2. Referring to Other Namespaces
      3. 7.3. Loading Other Namespaces
        1. 7.3.1. Loading from a File or Stream
        2. 7.3.2. Loading from the Classpath
          1. 7.3.2.1. Namespace Names vs. File Names
          2. 7.3.2.2. Loading Resources from the Classpath
          3. 7.3.2.3. Loading Namespaces from the Classpath
        3. 7.3.3. Loading and Referring Namespaces in One Step
        4. 7.3.4. Importing Java Classes
      4. 7.4. Bringing It All Together: Namespace Declarations
      5. 7.5. Symbols and Namespaces
        1. 7.5.1. Namespace Metadata
        2. 7.5.2. Forward Declarations
        3. 7.5.3. Namespace-Qualified Symbols and Keywords
        4. 7.5.4. Constructing Symbols and Keywords
        5. 7.5.5. Public and Private Vars
      6. 7.6. Advanced Namespace Operations
        1. 7.6.1. Querying Namespaces
        2. 7.6.2. Manipulating Namespaces
      7. 7.7. Namespaces As References
      8. 7.8. Summary
    12. 8. Metadata
      1. 8.1. Describing Your Code, in Code
      2. 8.2. Reading and Writing Metadata
      3. 8.3. Metadata-Preserving Operations
      4. 8.4. Read-Time Metadata
      5. 8.5. Metadata on Vars
        1. 8.5.1. Type Tags
        2. 8.5.2. Private Vars
      6. 8.6. Metadata on Reference Types
      7. 8.7. Summary
    13. 9. Multimethods and Hierarchies
      1. 9.1. Runtime Polymorphism Without Classes
      2. 9.2. Multimethods
        1. 9.2.1. Multiple Dispatch
        2. 9.2.2. Default Dispatch Values
      3. 9.3. Hierarchies
        1. 9.3.1. Querying Hierarchies
      4. 9.4. Hierarchies with Multimethods
        1. 9.4.1. Hierarchies with Java Classes
        2. 9.4.2. More Hierarchy Queries
        3. 9.4.3. Resolving Conflicts
        4. 9.4.4. Type Tags
      5. 9.5. User-Defined Hierarchies
      6. 9.6. Summary
    14. 10. Java Interoperability
      1. 10.1. Calling Java from Clojure
        1. 10.1.1. Java Interop Special Forms
        2. 10.1.2. Java Interop Preferred Forms
        3. 10.1.3. Clojure Types and Java Interfaces
        4. 10.1.4. Java Arrays
          1. 10.1.4.1. Creating Arrays
          2. 10.1.4.2. Manipulating Arrays
          3. 10.1.4.3. Iterating Over Arrays
      2. 10.2. Calling Clojure from Java
        1. 10.2.1. Loading and Evaluating Clojure Code
        2. 10.2.2. Using Clojure Functions and Vars
      3. 10.3. Creating Java Classes
        1. 10.3.1. Proxying Java Classes
        2. 10.3.2. Generating Java Classes
          1. 10.3.2.1. Ahead-of-Time Compilation
          2. 10.3.2.2. Basic gen-class Options
          3. 10.3.2.3. Defining Methods for the Generated Class
          4. 10.3.2.4. Adding State to the Generated Class
          5. 10.3.2.5. Adding Methods to the Generated Class
          6. 10.3.2.6. Adding Constructors and Factories
          7. 10.3.2.7. Exposing Superclass Members
          8. 10.3.2.8. Generating Command-Line Programs
          9. 10.3.2.9. Loading the Implementation
          10. 10.3.2.10. Namespace Declarations with gen-class
          11. 10.3.2.11. Simple Command-Line Program
      4. 10.4. Summary
    15. 11. Parallel Programming
      1. 11.1. Parallelism in Clojure
      2. 11.2. Agents
        1. 11.2.1. Agent Thread Pools
        2. 11.2.2. Agent Example
        3. 11.2.3. Concurrent Agent Performance
      3. 11.3. Concurrency Functions
        1. 11.3.1. Overhead and Performance
      4. 11.4. Futures and Promises
        1. 11.4.1. Futures
          1. 11.4.1.1. Controlling Futures
        2. 11.4.2. Promises
      5. 11.5. Java-based Threading
        1. 11.5.1. Creating a Thread
      6. 11.6. Summary
    16. 12. Macros and Metaprogramming
      1. 12.1. What Is Metaprogramming?
        1. 12.1.1. Code vs. Data
        2. 12.1.2. Homoiconicity
      2. 12.2. Macros
        1. 12.2.1. Working with Macros
          1. 12.2.1.1. Debugging Macros
        2. 12.2.2. Code Templating
          1. 12.2.2.1. Splicing Unquotes
        3. 12.2.3. Generating Symbols
        4. 12.2.4. When to Use Macros
        5. 12.2.5. Using Macros
          1. 12.2.5.1. Implementing a Control Structure
          2. 12.2.5.2. Implementing a Macro with Variadic Arguments
          3. 12.2.5.3. Implementing a Macro Using Recursion
        6. 12.2.6. Using Macros to Create DSLs
      3. 12.3. Summary
    17. 13. Datatypes and Protocols
      1. 13.1. Protocols
        1. 13.1.1. Protocols As Interfaces
      2. 13.2. Datatypes
      3. 13.3. Implementing Protocols and Interfaces
        1. 13.3.1. In-Line Methods
        2. 13.3.2. Extending Java Interfaces
        3. 13.3.3. Datatypes As Classes
      4. 13.4. Extending Protocols to Pre-Existing Types
        1. 13.4.1. Extending Java Classes and Interfaces
      5. 13.5. Reifying Anonymous Datatypes
      6. 13.6. Working with Datatypes and Protocols
        1. 13.6.1. A Complete Example
      7. 13.7. Advanced Datatypes
      8. 13.8. Summary
    18. 14. Performance
      1. 14.1. Profiling on the JVM
        1. 14.1.1. General Tips for Java Performance
        2. 14.1.2. Simple Profiling with Time
        3. 14.1.3. Using Java Profiling Tools
      2. 14.2. Memoization
      3. 14.3. Reflection and Type Hints
      4. 14.4. Working with Primitives
        1. 14.4.1. Loop Primitives
        2. 14.4.2. Unchecked Integer Arithmetic
        3. 14.4.3. Primitive Arrays
      5. 14.5. Transients
      6. 14.6. Var Lookups
      7. 14.7. Inlining
        1. 14.7.1. Macros and definline
      8. 14.8. Summary