Clojure Cookbook
Total Page:16
File Type:pdf, Size:1020Kb
Clojure Cookbook Luke VanderHart and Ryan Neufeld Clojure Cookbook by Luke VanderHart and Ryan Neufeld Copyright © 2014 Cognitect, Inc. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://my.safaribooksonline.com). For more information, contact our corporate/ institutional sales department: 800-998-9938 or [email protected]. Editor: Meghan Blanchette Indexer: Judith McConville Production Editor: Kristen Brown Cover Designer: Karen Montgomery Copyeditor: Amanda Kersey Interior Designer: David Futato Proofreader: Rachel Head Illustrator: Rebecca Demarest March 2014: First Edition Revision History for the First Edition: 2014-03-04: First release See http://oreilly.com/catalog/errata.csp?isbn=9781449366179 for release details. Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly Media, Inc. Clojure Cookbook, the image of an aardwolf, and related trade dress are trademarks of O’Reilly Media, Inc. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and O’Reilly Media, Inc. was aware of a trademark claim, the designations have been printed in caps or initial caps. While every precaution has been taken in the preparation of this book, the publisher and authors assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein. ISBN: 978-1-449-36617-9 [LSI] Table of Contents Preface. ix 1. Primitive Data. 1 1.1. Changing the Capitalization of a String 3 1.2. Cleaning Up Whitespace in a String 4 1.3. Building a String from Parts 5 1.4. Treating a String as a Sequence of Characters 7 1.5. Converting Between Characters and Integers 8 1.6. Formatting Strings 10 1.7. Searching a String by Pattern 12 1.8. Pulling Values Out of a String Using Regular Expressions 13 1.9. Performing Find and Replace on Strings 15 1.10. Splitting a String into Parts 17 1.11. Pluralizing Strings Based on a Quantity 18 1.12. Converting Between Strings, Symbols, and Keywords 20 1.13. Maintaining Accuracy with Extremely Large/Small Numbers 22 1.14. Working with Rational Numbers 24 1.15. Parsing Numbers 25 1.16. Truncating and Rounding Numbers 26 1.17. Performing Fuzzy Comparison 28 1.18. Performing Trigonometry 30 1.19. Inputting and Outputting Integers with Different Bases 31 1.20. Calculating Statistics on Collections of Numbers 32 1.21. Performing Bitwise Operations 36 1.22. Generating Random Numbers 37 1.23. Working with Currency 39 1.24. Generating Unique IDs 41 1.25. Obtaining the Current Date and Time 43 1.26. Representing Dates as Literals 44 iii 1.27. Parsing Dates and Times Using clj-time 46 1.28. Formatting Dates Using clj-time 47 1.29. Comparing Dates 49 1.30. Calculating the Length of a Time Interval 50 1.31. Generating Ranges of Dates and Times 52 1.32. Generating Ranges of Dates and Times Using Native Java Types 53 1.33. Retrieving Dates Relative to One Another 56 1.34. Working with Time Zones 58 1.35. Converting a Unix Timestamp to a Date 59 1.36. Converting a Date to a Unix Timestamp 61 2. Composite Data. 63 2.1. Creating a List 65 2.2. Creating a List from an Existing Data Structure 66 2.3. “Adding” an Item to a List 68 2.4. “Removing” an Item from a List 69 2.5. Testing for a List 70 2.6. Creating a Vector 71 2.7. “Adding” an Item to a Vector 72 2.8. “Removing” an Item from a Vector 73 2.9. Getting the Value at an Index 74 2.10. Setting the Value at an Index 76 2.11. Creating a Set 77 2.12. Adding and Removing Items from Sets 79 2.13. Testing Set Membership 80 2.14. Using Set Operations 82 2.15. Creating a Map 84 2.16. Retrieving Values from a Map 86 2.17. Retrieving Multiple Keys from a Map Simultaneously 89 2.18. Setting Keys in a Map 90 2.19. Using Composite Values as Map Keys 94 2.20. Treating Maps as Sequences (and Vice Versa) 96 2.21. Applying Functions to Maps 98 2.22. Keeping Multiple Values for a Key 100 2.23. Combining Maps 103 2.24. Comparing and Sorting Values 105 2.25. Removing Duplicate Elements from a Collection 109 2.26. Determining if a Collection Holds One of Several Values 111 2.27. Implementing Custom Data Structures: Red-Black Trees—Part I 112 2.28. Implementing Custom Data Structures: Red-Black Trees—Part II 115 3. General Computing. 121 iv | Table of Contents 3.1. Running a Minimal Clojure REPL 121 3.2. Interactive Documentation 123 3.3. Exploring Namespaces 125 3.4. Trying a Library Without Explicit Dependencies 126 3.5. Running Clojure Programs 127 3.6. Running Programs from the Command Line 130 3.7. Parsing Command-Line Arguments 132 3.8. Creating Custom Project Templates 135 3.9. Building Functions with Polymorphic Behavior 139 3.10. Extending a Built-In Type 145 3.11. Decoupling Consumers and Producers with core.async 146 3.12. Making a Parser for Clojure Expressions Using core.match 150 3.13. Querying Hierarchical Graphs with core.logic 153 3.14. Playing a Nursery Rhyme 159 4. Local I/O. 165 4.1. Writing to STDOUT and STDERR 165 4.2. Reading a Single Keystroke from the Console 167 4.3. Executing System Commands 168 4.4. Accessing Resource Files 171 4.5. Copying Files 173 4.6. Deleting Files or Directories 175 4.7. Listing Files in a Directory 176 4.8. Memory Mapping a File 178 4.9. Reading and Writing Text Files 179 4.10. Using Temporary Files 181 4.11. Reading and Writing Files at Arbitrary Positions 182 4.12. Parallelizing File Processing 183 4.13. Parallelizing File Processing with Reducers 185 4.14. Reading and Writing Clojure Data 188 4.15. Using edn for Configuration Files 190 4.16. Emitting Records as edn Values 194 4.17. Handling Unknown Tagged Literals When Reading Clojure Data 196 4.18. Reading Properties from a File 199 4.19. Reading and Writing Binary Files 201 4.20. Reading and Writing CSV Data 203 4.21. Reading and Writing Compressed Files 204 4.22. Working with XML Data 206 4.23. Reading and Writing JSON Data 207 4.24. Generating PDF Files 209 Table of Contents | v 4.25. Making a GUI Window with Scrollable Text 213 5. Network I/O and Web Services. 219 5.1. Making HTTP Requests 219 5.2. Performing Asynchronous HTTP Requests 221 5.3. Sending a Ping Request 223 5.4. Retrieving and Parsing RSS Data 224 5.5. Sending Email 226 5.6. Communicating over Queues Using RabbitMQ 229 5.7. Communicating with Embedded Devices via MQTT 236 5.8. Using ZeroMQ Concurrently 240 5.9. Creating a TCP Client 243 5.10. Creating a TCP Server 245 5.11. Sending and Receiving UDP Packets 248 6. Databases. 253 6.1. Connecting to an SQL Database 254 6.2. Connecting to an SQL Database with a Connection Pool 257 6.3. Manipulating an SQL Database 260 6.4. Simplifying SQL with Korma 266 6.5. Performing Full-Text Search with Lucene 270 6.6. Indexing Data with ElasticSearch 272 6.7. Working with Cassandra 277 6.8. Working with MongoDB 280 6.9. Working with Redis 284 6.10. Connecting to a Datomic Database 286 6.11. Defining a Schema for a Datomic Database 289 6.12. Writing Data to Datomic 293 6.13. Removing Data from a Datomic Database 296 6.14. Trying Datomic Transactions Without Committing Them 298 6.15. Traversing Datomic Indexes 300 7. Web Applications. 305 7.1. Introduction to Ring 305 7.2. Using Ring Middleware 307 7.3. Serving Static Files with Ring 309 7.4. Handling Form Data with Ring 311 7.5. Handling Cookies with Ring 312 7.6. Storing Sessions with Ring 314 7.7. Reading and Writing Request and Response Headers in Ring 316 7.8. Routing Requests with Compojure 318 7.9. Performing HTTP Redirects with Ring 320 vi | Table of Contents 7.10. Building a RESTful Application with Liberator 321 7.11. Templating HTML with Enlive 323 7.12. Templating with Selmer 330 7.13. Templating with Hiccup 334 7.14. Rendering Markdown Documents 337 7.15. Building Applications with Luminus 339 8. Performance and Production. 343 8.1. AOT Compilation 343 8.2. Packaging a Project into a JAR File 345 8.3. Creating a WAR File 348 8.4. Running an Application as a Daemon 352 8.5. Alleviating Performance Problems with Type Hinting 358 8.6. Fast Math with Primitive Java Arrays 360 8.7. Simple Profiling with Timbre 363 8.8. Logging with Timbre 365 8.9. Releasing a Library to Clojars 367 8.10. Using Macros to Simplify API Deprecations 369 9. Distributed Computation. 375 9.1. Building an Activity Feed System with Storm 376 9.2. Processing Data with an Extract Transform Load (ETL) Pipeline 385 9.3. Aggregating Large Files 389 9.4. Testing Cascalog Workflows 394 9.5. Checkpointing Cascalog Jobs 396 9.6. Explaining a Cascalog Query 398 9.7. Running a Cascalog Job on Elastic MapReduce 400 10. Testing. 403 10.1. Unit Testing 404 10.2.