Table of Contents

Copyright

Brief Table of Contents

Table of Contents

Praise for the First Edition

Foreword to the Second Edition

Foreword to the First Edition

Preface

Acknowledgments

About this Book

About Clojure

About the Cover Illustration

1. Foundations

Chapter 1. Clojure philosophy

1.1. The Clojure way

1.1.1. Simplicity

1.1.2. Freedom to focus

1.1.3. Empowerment

1.1.4. Clarity

1.1.5. Consistency

1.2. Why a(nother) Lisp?

1.2.1. Beauty

1.2.2. But what’s with all the parentheses?

1.3. Functional programming

1.3.1. A workable definition of functional programming

1.3.2. The implications of functional programming

1.4. Why Clojure isn’t especially object-oriented

1.4.1. Defining terms

1.4.2. Imperative “baked in”

1.4.3. Most of what OOP gives you, Clojure provides

1.5. Summary

Chapter 2. Drinking from the Clojure fire hose

2.1. Scalars: the base data types

2.1.1. Numbers

2.1.2. Integers

2.1.3. Floating-point numbers

2.1.4. Rationals

2.1.5. Symbols

2.1.6. Keywords

2.1.7. Strings

2.1.8. Characters

2.2. Putting things together: collections

2.2.1. Lists

2.2.2. Vectors

2.2.3. Maps

2.2.4. Sets

2.3. Making things happen: calling functions

2.4. Vars are not variables

2.5. Functions

2.5.1. Anonymous functions

2.5.2. Creating named functions with def and defn

2.5.3. Functions with multiple arities

2.5.4. In-place functions with #()

2.6. Locals, loops, and blocks

2.6.1. Blocks

2.6.2. Locals

2.6.3. Loops

2.7. Preventing things from happening: quoting

2.7.1. Evaluation

2.7.2. Quoting

2.7.3. Unquote

2.7.4. Unquote-splicing

2.7.5. Auto-gensym

2.8. Using host libraries via interop

2.8.1. Accessing static class members (Clojure only)

2.8.2. Creating instances

2.8.3. Accessing instance members with the . operator

2.8.4. Setting instance fields

2.8.5. The .. macro

2.8.6. The doto macro

2.8.7. Defining classes

2.9. Exceptional circumstances

2.9.1. Throwing and catching

2.10. Modularizing code with namespaces

2.10.1. Creating namespaces using ns

2.10.2. Loading other namespaces with :require

2.10.3. Loading and creating mappings with :refer

2.10.4. Creating mappings with :refer

2.10.5. Loading Java classes with :import

2.11. Summary

Chapter 3. Dipping your toes in the pool

3.1. Truthiness

3.1.1. What’s truth?

3.1.2. Don’t create Boolean objects

3.1.3. nil vs. false

3.2. Nil pun with care

3.3. Destructuring

3.3.1. Your assignment, should you choose to accept it

3.3.2. Destructuring with a vector

3.3.3. Destructuring with a map

3.3.4. Destructuring in function parameters

3.3.5. Destructuring vs. accessor methods

3.4. Using the REPL to experiment

3.4.1. Experimenting with seqs

3.4.2. Experimenting with graphics

3.4.3. Putting it all together

3.4.4. When things go wrong

3.4.5. Just for fun

3.5. Summary

2. Data types

Chapter 4. On scalars

4.1. Understanding precision

4.1.1. Truncation

4.1.2. Promotion

4.1.3. Overflow

4.1.4. Underflow

4.1.5. Rounding errors

4.2. Trying to be rational

4.2.1. Why be rational?

4.2.2. How to be rational

4.2.3. Caveats of rationality

4.3. When to use keywords

4.3.1. Applications of keywords

4.3.2. Qualifying your keywords

4.4. Symbolic resolution

4.4.1. Metadata

4.4.2. Symbols and namespaces

4.4.3. Lisp-1

4.5. Regular expressions—the second problem

4.5.1. Syntax

4.5.2. Regular-expression functions

4.5.3. Beware of mutable matchers

4.6. Summary

Chapter 5. Collection types

5.1. Persistence, sequences, and complexity

5.1.1. “You keep using that word. I do not think it means what you think it means.”

5.1.2. Sequence terms and what they mean

5.1.3. Big-O

5.2. Vectors: creating and using them in all their varieties

5.2.1. Building vectors

5.2.2. Large vectors

5.2.3. Vectors as stacks

5.2.4. Using vectors instead of reverse

5.2.5. Subvectors

5.2.6. Vectors as map entries

5.2.7. What vectors aren’t

5.3. Lists: Clojure’s code-form data structure

5.3.1. Lists like Lisps like

5.3.2. Lists as stacks

5.3.3. What lists aren’t

5.4. How to use persistent queues

5.4.1. A queue about nothing

5.4.2. Putting things on

5.4.3. Getting things

5.4.4. Taking things off

5.5. Persistent sets

5.5.1. Basic properties of Clojure sets

5.5.2. Keeping your sets in order with sorted-set

5.5.3. The contains? function

5.5.4. The clojure.set namespace

5.6. Thinking in maps

5.6.1. Hash maps

5.6.2. Keeping your keys in order with sorted maps

5.6.3. Keeping your insertions in order with array maps

5.7. Putting it all together: finding the position of items in a sequence

5.7.1. Implementation

5.8. Summary

3. Functional programming techniques

Chapter 6. Being lazy and set in your ways

6.1. On immutability: being set in your ways

6.1.1. What is immutability?

6.1.2. What is immutability for?

6.2. Structural sharing: a persistent toy

6.3. Laziness

6.3.1. Familiar laziness with logical-and

6.3.2. Understanding the lazy-seq recipe

6.3.3. Losing your head

6.3.4. Employing infinite sequences

6.3.5. The delay and force macros

6.4. Putting it all together: a lazy quicksort

6.4.1. The implementation

6.5. Summary

Chapter 7. Functional programming

7.1. Functions in all their forms

7.1.1. First-class functions

7.1.2. Higher-order functions

7.1.3. Pure functions

7.1.4. Named arguments

7.1.5. Constraining functions with pre- and postconditions

7.2. On closures

7.2.1. Functions returning closures

7.2.2. Closing over parameters

7.2.3. Passing closures as functions

7.2.4. Sharing closure context

7.3. Thinking recursively

7.3.1. Mundane recursion

7.3.2. Tail calls and recur

7.3.3. Don’t forget your trampoline

7.3.4. Continuation-passing style

7.4. Putting it all together: A* pathfinding

7.4.1. The world

7.4.2. Neighbors

7.4.3. The A* implementation

7.4.4. Notes about the A* implementation

7.5. Summary

4. Large-scale design

Chapter 8. Macros

8.1. Data is code is data

8.1.1. Syntax-quote, unquote, and splicing

8.1.2. Macro rules of thumb

8.2. Defining control structures

8.2.1. Defining control structures without syntax-quote

8.2.2. Defining control structures using syntax-quote and unquoting

8.3. Macros combining forms

8.4. Using macros to change forms

8.5. Using macros to control symbolic resolution time

8.5.1. Anaphora

8.5.2. (Arguably) useful selective name capturing

8.6. Using macros to manage resources

8.7. Putting it all together: macros returning functions

8.8. Summary

Chapter 9. Combining data and code

9.1. Namespaces

9.1.1. Creating namespaces

9.1.2. Expose only what’s needed

9.1.3. Declarative inclusions and exclusions

9.2. Exploring Clojure multimethods with the Universal Design Pattern

9.2.1. The parts

9.2.2. Basic use of the Universal Design Pattern

9.2.3. Multimethods to the rescue

9.2.4. Ad hoc hierarchies for inherited behaviors

9.2.5. Resolving conflict in hierarchies

9.2.6. Arbitrary dispatch for true maximum power

9.3. Types, protocols, and records

9.3.1. Records

9.3.2. Protocols

9.3.3. Building from a more primitive base with deftype

9.4. Putting it all together: a fluent builder for chess moves

9.4.1. Java implementation

9.4.2. Clojure implementation

9.5. Summary

Chapter 10. Mutation and concurrency

10.1. When to use refs

10.1.1. Using refs for a mutable game board

10.1.2. Transactions

10.1.3. Embedded transactions

10.1.4. The things that STM makes easy

10.1.5. Potential downsides

10.1.6. The things that make STM unhappy

10.2. Refactoring with refs

10.2.1. Fixing the game board example

10.2.2. Commutative change with commute

10.2.3. Vulgar change with ref-set

10.2.4. Refs under stress

10.3. When to use agents

10.3.1. In-process vs. distributed concurrency models

10.3.2. Controlling I/O with an agent

10.3.3. The difference between send and send-off

10.3.4. Error handling

10.3.5. When not to use agents

10.4. When to use atoms

10.4.1. Sharing across threads

10.4.2. Using atoms in transactions

10.5. When to use locks

10.5.1. Safe mutation through locking

10.5.2. Using Java’s explicit locks

10.6. Vars and dynamic binding

10.6.1. The binding macro

10.6.2. Creating a named var

10.6.3. Creating anonymous vars

10.6.4. Dynamic scope

10.7. Summary

Chapter 11. Parallelism

11.1. When to use futures

11.1.1. Futures as callbacks

11.2. When to use promises

11.2.1. Parallel tasks with promises

11.2.2. Callback API to blocking API

11.2.3. Deterministic deadlocks

11.3. Parallel operations

11.3.1. The pvalues macro

11.3.2. The pmap function

11.3.3. The pcalls function

11.4. A brief introduction to reducer/fold

11.5. Summary

5. Host symbiosis

Chapter 12. Java.next

12.1. Generating objects on the fly with proxy

12.1.1. A simple dynamic web service

12.2. Clojure gen-class and GUI programming

12.2.1. Namespaces as class specifications

12.2.2. The guts of namespace compilation

12.2.3. Exploring user interface design and development with Clojure

12.3. Clojure’s relationship to Java arrays

12.3.1. Types of arrays: primitive and reference

12.3.2. Array mutability

12.3.3. Arrays’ unfortunate naming convention

12.3.4. Multidimensional arrays

12.3.5. Variadic method/constructor calls

12.4. All Clojure functions implement ...

12.4.1. The java.util.Comparator interface

12.4.2. The java.lang.Runnable interface

12.4.3. The java.util.concurrent.Callable interface

12.5. Using Clojure data structures in Java APIs

12.5.1. The java.util.List interface

12.5.2. The java.lang.Comparable interface

12.5.3. The java.util.RandomAccess interface

12.5.4. The java.util.Collection interface

12.5.5. The java.util.Set interface

12.6. The definterface macro

12.6.1. Generating interfaces on the fly

12.7. Be wary of exceptions

12.7.1. A bit of background regarding exceptions

12.7.2. Runtime vs. compile-time exceptions

12.7.3. Handling exceptions

12.7.4. Custom exceptions

12.8. Summary

Chapter 13. Why ClojureScript?

13.1. Implementation vs. interface

13.2. Compiler internals: analysis vs. emission

13.2.1. Stages of compilation

13.2.2. Web Audio

13.2.3. Advanced compilation

13.2.4. Generating an externs.js file

13.3. Compile vs. run

13.4. Summary

6. Tangential considerations

Chapter 14. Data-oriented programming

14.1. Code as code, and data as data

14.1.1. A strict line betwixt

14.1.2. ORMG

14.1.3. Common ways to derive information from data

14.1.4. PLOP

14.2. Data as data

14.2.1. The benefits of value

14.2.2. Tagged literals

14.3. Data as code

14.3.1. The data-programmable engine

14.3.2. Examples of data-programmable engines

14.3.3. Case study: simple event sourcing

14.4. Code as data as code

14.4.1. Hart’s discovery and homoiconicity

14.4.2. Clojure code is data

14.4.3. Putting parentheses around the specification

14.5. Summary

Chapter 15. Performance

15.1. Type hints

15.1.1. Advantages of type adornment

15.1.2. Type-hinting arguments and returns

15.1.3. Type-hinting objects

15.2. Transients

15.2.1. Ephemeral garbage

15.2.2. Transients compare in efficiency to mutable collections

15.3. Chunked sequences

15.3.1. Regaining one-at-a-time laziness

15.4. Memoization

15.4.1. Reexamining memoization

15.4.2. A memoization protocol

15.4.3. Abstraction-oriented programming

15.5. Understanding coercion

15.5.1. Using primitive longs

15.5.2. Using primitive doubles

15.5.3. Using auto-promotion

15.6. Reducibles

15.6.1. An example reducible collection

15.6.2. Deriving your first reducing function transformer

15.6.3. More reducing function transformers

15.6.4. Reducible transformers

15.6.5. Performance of reducibles

15.6.6. Drawbacks of reducibles

15.6.7. Integrating reducibles with Clojure reduce

15.6.8. The fold function: reducing in parallel

15.7. Summary

Chapter 16. Thinking programs

16.1. A problem of search

16.1.1. A brute-force Sudoku solver

16.1.2. Declarative is the goal

16.2. Thinking data via unification

16.2.1. Potential equality, or satisfiability

16.2.2. Substitution

16.2.3. Unification

16.3. An introduction to core.logic

16.3.1. It’s all about unification

16.3.2. Relations

16.3.3. Subgoals

16.4. Constraints

16.4.1. An introduction to constraint programming

16.4.2. Limiting binding via finite domains

16.4.3. Solving Sudoku with finite domains

16.5. Summary

Chapter 17. Clojure changes the way you think

17.1. Thinking in the domain

17.1.1. A ubiquitous DSL

17.1.2. Implementing a SQL-like DSL to generate queries

17.1.3. A note about Clojure’s approach to DSLs

17.2. Testing

17.2.1. Some useful unit-testing techniques

17.2.2. Contracts programming

17.3. Invisible design patterns

17.3.1. Clojure’s first-class design patterns

17.4. Error handling and debugging

17.4.1. Error handling

17.4.2. Debugging

17.5. Fare thee well

 Resources

Index

List of Figures

List of Tables

List of Listings

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.49.190