Foreword |
|
xxiii | |
|
Preface |
|
xxv | |
Acknowledgments |
|
xxxv | |
About the Author |
|
xxxvii | |
|
Part I Functional Programming |
|
|
1 | (214) |
|
Chapter 1 Concepts of Functional Programming |
|
|
3 | (6) |
|
1.1 What Is Functional Programming? |
|
|
3 | (1) |
|
|
4 | (2) |
|
1.3 From Functions to Functional Programming Concepts |
|
|
6 | (1) |
|
|
7 | (2) |
|
Chapter 2 Functions in Programming Languages |
|
|
9 | (12) |
|
|
9 | (1) |
|
|
10 | (2) |
|
2.3 Functions Defined as Methods |
|
|
12 | (1) |
|
2.4 Operators Defined as Methods |
|
|
12 | (1) |
|
|
13 | (1) |
|
|
14 | (1) |
|
|
15 | (1) |
|
|
16 | (1) |
|
|
16 | (1) |
|
|
17 | (2) |
|
|
19 | (2) |
|
|
21 | (18) |
|
3.1 Pure and Impure Functions |
|
|
21 | (2) |
|
|
23 | (2) |
|
3.3 Expressions Versus Statements |
|
|
25 | (1) |
|
|
26 | (2) |
|
|
28 | (1) |
|
3.6 Implementation of Mutable State |
|
|
29 | (2) |
|
|
31 | (1) |
|
|
32 | (3) |
|
3.9 Updating Collections of Mutable/Immutable Objects |
|
|
35 | (1) |
|
|
36 | (3) |
|
Chapter 4 Case Study: Active-Passive Sets |
|
|
39 | (8) |
|
4.1 Object-Oriented Design |
|
|
39 | (2) |
|
|
41 | (2) |
|
|
43 | (1) |
|
|
44 | (3) |
|
Chapter 5 Pattern Matching and Algebraic Data Types |
|
|
47 | (16) |
|
|
47 | (1) |
|
|
48 | (2) |
|
|
50 | (1) |
|
5.4 Revisiting Functional Lists |
|
|
51 | (2) |
|
|
53 | (3) |
|
5.6 Illustration: List Zipper |
|
|
56 | (3) |
|
|
59 | (1) |
|
|
60 | (3) |
|
Chapter 6 Recursive Programming |
|
|
63 | (16) |
|
6.1 The Need for Recursion |
|
|
63 | (2) |
|
|
65 | (2) |
|
6.3 Key Principles of Recursive Algorithms |
|
|
67 | (2) |
|
|
69 | (2) |
|
|
71 | (2) |
|
6.6 Examples of Tail Recursive Functions |
|
|
73 | (4) |
|
|
77 | (2) |
|
Chapter 7 Recursion on Lists |
|
|
79 | (20) |
|
7.1 Recursive Algorithms as Equalities |
|
|
79 | (1) |
|
|
80 | (2) |
|
|
82 | (2) |
|
7.4 Building Lists from the Execution Stack |
|
|
84 | (1) |
|
7.5 Recursion on Multiple/Nested Lists |
|
|
85 | (3) |
|
7.6 Recursion on Sublists Other Than the Tail |
|
|
88 | (2) |
|
7.7 Building Lists in Reverse Order |
|
|
90 | (2) |
|
7.8 Illustration: Sorting |
|
|
92 | (2) |
|
7.9 Building Lists Efficiently |
|
|
94 | (2) |
|
|
96 | (3) |
|
Chapter 8 Case Study: Binary Search Trees |
|
|
99 | (16) |
|
|
99 | (1) |
|
8.2 Sets of Integers as Binary Search Trees |
|
|
100 | (2) |
|
8.3 Implementation Without Rebalancing |
|
|
102 | (5) |
|
|
107 | (6) |
|
|
113 | (2) |
|
Chapter 9 Higher-Order Functions |
|
|
115 | (22) |
|
|
115 | (3) |
|
|
118 | (2) |
|
|
120 | (3) |
|
9.4 Functions Versus Methods |
|
|
123 | (1) |
|
9.5 Single-Abstract-Method Interfaces |
|
|
124 | (1) |
|
|
125 | (5) |
|
|
130 | (3) |
|
|
133 | (1) |
|
|
133 | (4) |
|
Chapter 10 Standard Higher-Order Functions |
|
|
137 | (20) |
|
10.1 Functions with Predicate Arguments |
|
|
137 | (3) |
|
|
140 | (1) |
|
|
141 | (5) |
|
|
146 | (2) |
|
10.5 iterate, tabulate, and unfold |
|
|
148 | (1) |
|
10.6 sortWith, sortBy, maxBy, and minBy |
|
|
149 | (1) |
|
10.7 groupBy and groupMap |
|
|
150 | (2) |
|
10.8 Implementing Standard Higher-Order Functions |
|
|
152 | (1) |
|
10.9 foreach, map, flatMap, and for-Comprehensions |
|
|
153 | (2) |
|
|
155 | (2) |
|
Chapter 11 Case Study: File Systems as Trees |
|
|
157 | (16) |
|
|
157 | (1) |
|
11.2 A Node-Searching Helper Function |
|
|
158 | (1) |
|
11.3 String Representation |
|
|
158 | (2) |
|
|
160 | (4) |
|
|
164 | (4) |
|
|
168 | (1) |
|
|
169 | (3) |
|
|
172 | (1) |
|
Chapter 12 Lazy Evaluation |
|
|
173 | (22) |
|
12.1 Delayed Evaluation of Arguments |
|
|
173 | (1) |
|
|
174 | (2) |
|
|
176 | (3) |
|
12.4 Internal Domain-Specific Languages |
|
|
179 | (1) |
|
12.5 Streams as Lazily Evaluated Lists |
|
|
180 | (2) |
|
12.6 Streams as Pipelines |
|
|
182 | (2) |
|
12.7 Streams as Infinite Data Structures |
|
|
184 | (1) |
|
|
184 | (3) |
|
12.9 Lists, Streams, Iterators, and Views |
|
|
187 | (3) |
|
12.10 Delayed Evaluation of Fields and Local Variables |
|
|
190 | (1) |
|
12.11 Illustration: Subset-Sum |
|
|
191 | (2) |
|
|
193 | (2) |
|
Chapter 13 Handling Failures |
|
|
195 | (10) |
|
13.1 Exceptions and Special Values |
|
|
195 | (2) |
|
|
197 | (1) |
|
|
198 | (1) |
|
|
199 | (2) |
|
13.5 Higher-Order Functions and Pipelines |
|
|
201 | (3) |
|
|
204 | (1) |
|
Chapter 14 Case Study: Trampolines |
|
|
205 | (10) |
|
14.1 Tail-Call Optimization |
|
|
205 | (1) |
|
14.2 Trampolines for Tail-Calls |
|
|
206 | (1) |
|
14.3 Tail-Call Optimization in Java |
|
|
207 | (2) |
|
14.4 Dealing with Non-Tail-Calls |
|
|
209 | (4) |
|
|
213 | (2) |
|
|
215 | (38) |
|
Chapter 15 Types (and Related Concepts) |
|
|
217 | (36) |
|
|
217 | (5) |
|
|
222 | (1) |
|
|
223 | (1) |
|
|
224 | (1) |
|
|
225 | (4) |
|
|
229 | (3) |
|
|
232 | (3) |
|
|
235 | (6) |
|
|
241 | (4) |
|
|
245 | (5) |
|
|
250 | (3) |
|
Part II Concurrent Programming |
|
|
253 | (180) |
|
Chapter 16 Concepts of Concurrent Programming |
|
|
255 | (6) |
|
16.1 Non-sequential Programs |
|
|
255 | (3) |
|
16.2 Concurrent Programming Concepts |
|
|
258 | (1) |
|
|
259 | (2) |
|
Chapter 17 Threads and Nondeterminism |
|
|
261 | (10) |
|
17.1 Threads of Execution |
|
|
261 | (2) |
|
17.2 Creating Threads Using Lambda Expressions |
|
|
263 | (1) |
|
17.3 Nondeterminism of Multithreaded Programs |
|
|
263 | (1) |
|
|
264 | (2) |
|
17.5 Testing and Debugging Multithreaded Programs |
|
|
266 | (2) |
|
|
268 | (3) |
|
Chapter 18 Atomicity and Locking |
|
|
271 | (14) |
|
|
271 | (2) |
|
18.2 Non-atomic Operations |
|
|
273 | (1) |
|
18.3 Atomic Operations and Non-atomic Composition |
|
|
274 | (4) |
|
|
278 | (1) |
|
|
279 | (2) |
|
18.6 Choosing Locking Targets |
|
|
281 | (2) |
|
|
283 | (2) |
|
Chapter 19 Thread-Safe Objects |
|
|
285 | (12) |
|
|
285 | (1) |
|
19.2 Encapsulating Synchronization Policies |
|
|
286 | (2) |
|
19.3 Avoiding Reference Escape |
|
|
288 | (1) |
|
19.4 Public and Private Locks |
|
|
289 | (1) |
|
19.5 Leveraging Immutable Types |
|
|
290 | (3) |
|
|
293 | (2) |
|
|
295 | (2) |
|
Chapter 20 Case Study: Thread-Safe Queue |
|
|
297 | (10) |
|
20.1 Queues as Pairs of Lists |
|
|
297 | (1) |
|
20.2 Single Public Lock Implementation |
|
|
298 | (3) |
|
20.3 Single Private Lock Implementation |
|
|
301 | (2) |
|
20.4 Applying Lock Splitting |
|
|
303 | (2) |
|
|
305 | (2) |
|
|
307 | (14) |
|
21.1 Fire-and-Forget Asynchronous Execution |
|
|
307 | (2) |
|
21.2 Illustration: Parallel Server |
|
|
309 | (3) |
|
21.3 Different Types of Thread Pools |
|
|
312 | (2) |
|
21.4 Parallel Collections |
|
|
314 | (4) |
|
|
318 | (3) |
|
Chapter 22 Synchronization |
|
|
321 | (16) |
|
22.1 Illustration of the Need for Synchronization |
|
|
321 | (3) |
|
|
324 | (1) |
|
|
325 | (3) |
|
22.4 Debugging Deadlocks with Thread Dumps |
|
|
328 | (2) |
|
22.5 The Java Memory Model |
|
|
330 | (5) |
|
|
335 | (2) |
|
Chapter 23 Common Synchronizers |
|
|
337 | (18) |
|
|
337 | (2) |
|
23.2 Latches and Barriers |
|
|
339 | (2) |
|
|
341 | (2) |
|
|
343 | (6) |
|
|
349 | (4) |
|
|
353 | (2) |
|
Chapter 24 Case Study: Parallel Execution |
|
|
355 | (14) |
|
24.1 Sequential Reference Implementation |
|
|
355 | (1) |
|
24.2 One New Thread per Task |
|
|
356 | (1) |
|
24.3 Bounded Number of Threads |
|
|
357 | (2) |
|
24.4 Dedicated Thread Pool |
|
|
359 | (1) |
|
|
360 | (1) |
|
|
361 | (1) |
|
24.7 Parallel Collections |
|
|
362 | (1) |
|
24.8 Asynchronous Task Submission Using Conditions |
|
|
362 | (5) |
|
24.9 Two-Semaphore Implementation |
|
|
367 | (1) |
|
|
368 | (1) |
|
Chapter 25 Futures and Promises |
|
|
369 | (12) |
|
|
369 | (2) |
|
25.2 Futures as Synchronizers |
|
|
371 | (3) |
|
25.3 Timeouts, Failures, and Cancellation |
|
|
374 | (1) |
|
|
375 | (1) |
|
|
375 | (2) |
|
25.6 Illustration: Thread-Safe Caching |
|
|
377 | (3) |
|
|
380 | (1) |
|
Chapter 26 Functional-Concurrent Programming |
|
|
381 | (18) |
|
26.1 Correctness and Performance Issues with Blocking |
|
|
381 | (3) |
|
|
384 | (1) |
|
26.3 Higher-Order Functions on Futures |
|
|
385 | (3) |
|
26.4 Function flatMap on Futures |
|
|
388 | (2) |
|
26.5 Illustration: Parallel Server Revisited |
|
|
390 | (3) |
|
26.6 Functional-Concurrent Programming Patterns |
|
|
393 | (4) |
|
|
397 | (2) |
|
Chapter 27 Minimizing Thread Blocking |
|
|
399 | (18) |
|
|
399 | (3) |
|
27.2 Lock-Free Data Structures |
|
|
402 | (3) |
|
|
405 | (1) |
|
27.4 Asynchronous Programming |
|
|
406 | (1) |
|
|
407 | (4) |
|
|
411 | (1) |
|
27.7 Non-blocking Synchronization |
|
|
412 | (2) |
|
|
414 | (3) |
|
Chapter 28 Case Study: Parallel Strategies |
|
|
417 | (16) |
|
|
417 | (2) |
|
28.2 Sequential Implementation with Timeout |
|
|
419 | (1) |
|
28.3 Parallel Implementation Using invokeAny |
|
|
420 | (1) |
|
28.4 Parallel Implementation Using CompletionService |
|
|
421 | (1) |
|
28.5 Asynchronous Implementation with Scala Futures |
|
|
422 | (4) |
|
28.6 Asynchronous Implementation with CompletableFuture |
|
|
426 | (1) |
|
28.7 Caching Results from Strategies |
|
|
427 | (4) |
|
|
431 | (2) |
|
Appendix A Features of Java and Kotlin |
|
|
433 | (30) |
|
A.1 Functions in Java and Kotlin |
|
|
433 | (3) |
|
|
436 | (1) |
|
A.3 Pattern Matching and Algebraic Data Types |
|
|
437 | (2) |
|
A.4 Recursive Programming |
|
|
439 | (1) |
|
A.5 Higher-Order Functions |
|
|
440 | (6) |
|
|
446 | (3) |
|
|
449 | (2) |
|
|
451 | (2) |
|
|
453 | (1) |
|
A.10 Atomicity and Locking |
|
|
454 | (1) |
|
|
455 | (2) |
|
|
457 | (2) |
|
|
459 | (1) |
|
A.14 Futures and Functional-Concurrent Programming |
|
|
460 | (1) |
|
A.15 Minimizing Thread Blocking |
|
|
461 | (2) |
Glossary |
|
463 | (6) |
Index |
|
469 | |