You are previewing Practical Clojure.

Practical Clojure

Cover of Practical Clojure by Stuart Sierra... Published by Apress
  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?
      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
    5. 3.5. Deliberate Side Effects
      1. 3.5.1.
    6. 3.6. Functional Programming Techniques
      1. 3.6.1. First-Class Functions
      2. 3.6.2. Closures
      3. 3.6.3. Currying and Composing 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
      2. 4.2.2. Strings
      3. 4.2.3. Boolean
      4. 4.2.4. Characters
      5. 4.2.5. Keywords
    3. 4.3. Collections
      1. 4.3.1. Lists
      2. 4.3.2. Vectors
      3. 4.3.3. Maps
      4. 4.3.4. Sets
    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
      3. 5.4.3. Lazy Sequences and Memory Management
    5. 5.5. The Sequence API
      1. 5.5.1. Sequence Creation
    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
    2. 6.2. Refs and Transactions
      1. 6.2.1. Creating and Accessing refs
      2. 6.2.2. Updating refs
    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
      2. 6.4.2. Errors and Agents
      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
      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
    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
    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
      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
      2. 12.2.2. Code Templating
      3. 12.2.3. Generating Symbols
      4. 12.2.4. When to Use Macros
      5. 12.2.5. Using Macros
      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
O'Reilly logo

Chapter 6. State Management

State in an Immutable World

As much as possible, Clojure advocates eliminating state from programs. In general, data should be passed and returned from functions in a purely functional way. It keeps things clean, protected, and parallelizable.

Often, however, that's simply not possible. The real world is full of changing concepts and so real programs are full of state. If you're writing a word processor, the current document has a state. If you're writing a game, the objects in the game world exist have state. If you're writing financial software, the amount of money in an account is state. This is a fact of the way the world is and the way humans think, and programs need to be able to model it effectively.

With today's ...

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