Preface
Introduction
- Who This Book Is For
- How to Use This Book
- What This Book Is Not
- A Note on Versions
- About the Author
Chapter 1: Getting Started
- Installing Clojure
- The REPL
- Creating a New Project
- The -main Function
- println — Clojure’s puts
- String Formatting with str and format
- Functions
- Chapter Exercises
- Summary
Chapter 2: Syntax and Data Literals
- S-Expressions
- Numbers
- Strings and Characters
- Keywords
- Symbols
- Lists
- Vectors
- Maps
- Sets
- Homoiconicity: Code Is Data
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 3: Immutability and Persistent Data Structures
- Persistent Data Structures
- Core Operations
- Why Immutability Matters
- Transients: Escape Hatch for Performance
- Let Bindings
- Threading Macros
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 4: Functions
- defn — Named Functions
- Multi-Arity Functions
- Variadic Functions
- Anonymous Functions
- Higher-Order Functions
- Closures
- juxt — Apply Multiple Functions
- some-fn and every-pred
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 5: Control Flow
- if and when
- Truthiness
- cond — Multi-Way Branching
- do — Grouping Expressions
- loop / recur — Iteration Without Mutation
- for — List Comprehension
- doseq and dotimes — Side Effects Only
- some and every? — Existential Checks
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 6: Namespaces and Code Organization
- ns — The Namespace Declaration
- :require — Loading Clojure Namespaces
- Creating a Namespace
- :import — Java Classes
- The Classpath
- require vs use vs refer
- Reloading Code
- project.clj vs deps.edn
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 7: Sequences and Laziness
- The Seq Abstraction
- map, filter, reduce — The Big Three
- The Rest of the Toolkit
- Sequences on Maps
- Sequences on Strings
- Lazy Sequences
- The Threading Macros Revisited
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 8: Destructuring
- Vector Destructuring
- Map Destructuring
- Destructuring in Function Parameters
- Destructuring in let and loop
- Destructuring in for
- Real-World Example: Parsing API Responses
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 9: Java Interop
- Why Java Interop Matters
- Calling Methods
- Creating Objects
- doto — Mutating a Java Object
- Static Fields and Enums
- Type Hints for Performance
- Arrays
- Importing Java Classes
- Real Examples
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 10: Concurrency and State
- The Identity/Value Separation
- Atoms — Independent, Synchronous State
- Refs and Software Transactional Memory (STM)
- Agents — Asynchronous Updates
- Vars and Dynamic Binding
- Futures and Promises
- core.async — Channels and Go Blocks
- Choosing the Right Reference Type
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 11: Macros and Metaprogramming
- Why Macros?
- Syntax Quoting, Unquote, and Unquote-Splicing
- Writing Your First Macro
- Debugging Macros
- Auto-Gensym for Hygiene
- Common Macro Patterns
- When NOT to Use Macros
- Macros vs Ruby Metaprogramming
- Try It Yourself
- Chapter Exercises
- Summary
Chapter 12: Building a Project
- The Project: bkmrk
- Project Setup
- The Data Model
- Persistence
- Command Handling
- CLI Entry Point
- Testing
- Building and Running
- The REPL-Driven Workflow in Practice
- Project Structure Recap
- Try It Yourself
- Chapter Exercises
- Summary
Appendix A: Resources
- Official Documentation
- Books
- Online Learning
- Editor Support
- Libraries Worth Knowing
- Community
- Staying in Touch with Ruby
Appendix B: Exercise Answers
- Chapter 1: Getting Started
- Chapter 2: Syntax and Data Literals
- Chapter 3: Immutability and Persistent Data Structures
- Chapter 4: Functions
- Chapter 5: Control Flow
- Chapter 6: Namespaces and Code Organization
- Chapter 7: Sequences and Laziness
- Chapter 8: Destructuring
- Chapter 9: Java Interop
- Chapter 10: Concurrency and State
- Chapter 11: Macros and Metaprogramming
- Chapter 12: Building a Project