S h elve i n : P r og r a mmi n g La ng uag e s/Clojure For weeks, months —nay!—from the very moment you were born, you’ve felt it calling to you At long last you’ll be united with the programming language you’ve been longing for: Clojure! • Wield Clojure’s core functions • Use Emacs for Clojure development • Write macros to modify Clojure itself • Use Clojure’s tools to simplify concurrency and parallel programming Clojure for the Brave and True assumes no prior experience with Clojure, the Java Virtual Machine, or functional programming Are you ready, brave reader, to meet your true destiny? Grab your best pair of parentheses—you’re about to embark on an epic journey into the world of Clojure! Daniel Higginbotham has been a professional programmer for 11 years, half of that at McKinsey & Company, where he used Clojure to build mobile and web applications He has also contributed to the curriculum for ClojureBridge, an organization that offers free, beginner-friendly Clojure workshops for women Daniel blogs about life and programming at http://flyingmachinestudios.com/, and can be found on Twitter, @nonrecursive He lives in Durham, North Carolina, with his wife and four cats C o v e r s C l o j u r e 1.7 r e q u i r e s J ava 1.6 or l ate r $34.95 ($40.95 CDN) w w w.nostarch.com THE FINEST IN G E E K E N T E R TA I N M E N T ™ Daniel Higginbotham About t he Au tho r And learn h o w to for The As a Lisp-style functional programming language, Clojure lets you write robust and elegant code, and because it runs on the Java Virtual Machine, you can take advantage of the vast Java ecosystem. Clojure for the Brave and True offers a “dessert-first” approach: you’ll start playing with real programs immediately, as you steadily acclimate to the abstract but powerful features of Lisp and functional programming Inside you’ll find an offbeat, practical guide to Clojure, filled with quirky sample programs that catch cheese thieves and track glittery vampires Clojure Brave True Join the Ranks of Noble Clojurists Clojure for The Brave And True learn the ultimate language and become a better programmer Daniel Higginbotham Clojure for the Brave and True Clojure for the Brave and True Copyright © 2015 by Daniel Higginbotham All rights reserved No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher Printed in USA First printing 19 18 17 16 15 ISBN-10: 1-59327-591-9 ISBN-13: 978-1-59327-591-4 Publisher: William Pollock Production Editor: Riley Hoffman Cover Design: Beth Middleworth and Daniel and Jessica Higginbotham Cover and Interior Illustrations: Jessica Higginbotham Interior Design: Octopod Studios Developmental Editors: Hayley Baker and Seph Kramer Technical Reviewer: Alan Dipert Copyeditor: Anne Marie Walker Compositors: Riley Hoffman and Susan Glinert Stevens Proofreader: Emelie Burnette For information on distribution, translations, or bulk sales, please contact No Starch Press, Inc directly: No Starch Press, Inc 245 8th Street, San Francisco, CA 94103 phone: 415.863.9900; info@nostarch.com www.nostarch.com Library of Congress Cataloging-in-Publication Data Higginbotham, Daniel Clojure for the brave and true : learn the ultimate language and become a better programmer / by Daniel Higginbotham pages cm Includes index Summary: "Guide to the functional programming language Clojure Teaches tools and techniques for writing programs in Clojure Covers how to wield and compose Clojure's core functions; use Emacs for Clojure development; write macros to modify the Clojure programming language; and use Clojure's tools to simplify concurrency and parallel programming" Provided by publisher ISBN 978-1-59327-591-4 ISBN 1-59327-591-9 Clojure (Computer program language) I Title QA76.73.C565H54 2015 005.13'3 dc23 2015014205 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc Other product and company names mentioned herein may be the trademarks of their respective owners Rather than use a trademark symbol with every occurrence of a trademarked name, we are using the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark The information in this book is distributed on an “As Is” basis, without warranty While every precaution has been taken in the preparation of this work, neither the author nor No Starch Press, Inc shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in it About the Author Daniel Higginbotham has been a professional programmer for 11 years, half of that at McKinsey & Company, where he used Clojure to build mobile and web applications He has also contributed to the curriculum for ClojureBridge, an organization that offers free, beginner-friendly Clojure workshops for women Daniel blogs about life and programming at http://flyingmachinestudios.com/, and can be found on Twitter, @nonrecursive He lives in Durham, North Carolina, with his wife and four cats About the Technical Reviewer Alan Dipert first heard about Lisp when he was 10 years old After it was described to him, he said “That sounds dumb.” In 2009, he learned Clojure and revised his opinion Alan has designed and built Clojure systems, conducted Clojure trainings, and spoken at Clojure conferences You can keep track of Alan’s work and recent opinions by visiting http:// tailrecursion.com/~alan or by following him on Twitter, @alandipert For Jess Brief Contents Foreword by Alan Dipert xvii Acknowledgments xix Introduction xxi Part I: Environment Setup Chapter 1: Building, Running, and the REPL Chapter 2: How to Use Emacs, an Excellent Clojure Editor 11 Part II: Language Fundamentals Chapter 3: Do Things: A Clojure Crash Course 35 Chapter 4: Core Functions in Depth 71 Chapter 5: Functional Programming 97 Chapter 6: Organizing Your Project: A Librarian’s Tale 125 Chapter 7: Clojure Alchemy: Reading, Evaluation, and Macros 147 Chapter 8: Writing Macros 165 Part III: Advanced Topics Chapter 9: The Sacred Art of Concurrent and Parallel Programming 189 Chapter 10: Clojure Metaphysics: Atoms, Refs, Vars, and Cuddle Zombies 207 Chapter 11: Mastering Concurrent Processes with core.async 233 Chapter 12: Working with the JVM 247 Chapter 13: Creating and Extending Abstractions with Multimethods, Protocols, and Records 265 (println "My" (:thing fileset) verb "on fire!") fileset)))) Listing B-2: The full code for composable Boot tasks that announce something’s on fire Here’s how you’d run this on the command line: boot what -t "pants" -p – fire And here’s how you’d run it in the REPL: (boot (what :thing "pants" :pluralize true) (fire)) Wait a minute, what’s that boot call doing there? And what’s with fileset at u and v? In Micha’s words, “The boot macro takes care of setup and cleanup (creating the initial fileset, stopping servers started by tasks, things like that) Tasks are functions, so you can call them directly, but if they use the fileset, they will fail unless you call them via the boot macro.” Let’s take a closer look at filesets Filesets Earlier I mentioned that middleware is for creating domain-specific function pipelines All that means is that each handler expects to receive domainspecific data and returns domain-specific data With Ring, for example, each handler expects to receive a request map representing the HTTP request, which might look something like this: {:server-port 80 :request-method :get :scheme :http} Each handler can choose to modify this request map in some way before passing it on to the next handler, say, by adding a :params key with a nice Clojure map of all query string and POST parameters Ring handlers return a response map, which consists of the keys :status, :headers, and :body, and once again each handler can transform this data in some way before returning it to its parent handler In Boot, each handler receives and returns a fileset The fileset abstraction lets you treat files on your filesystem as immutable data, and this is a great innovation for build tools because building projects is so file-centric For example, your project might need to place temporary, intermediary files on the filesystem Usually, with most build tools, these files get placed in some specially named place, say, project/target/tmp The problem with this is that project/target/tmp is effectively a global variable, and other tasks can accidentally muck it up 288 Appendix B Boot’s fileset abstraction solves this problem by adding a layer of indirection on top of the filesystem Let’s say Task A creates File X and tells the fileset to store it Behind the scenes, the fileset stores the file in an anonymous, temporary directory The fileset then gets passed to Task B, and Task B modifies File X and asks the fileset to store the result Behind the scenes, a new file, File Y, is created and stored, but File X remains untouched In Task B, an updated fileset is returned This is the equivalent of doing assoc-in with a map: Task A can still access the original fileset and the files it references And you didn’t even use any of this cool file management functionality in the what and fire tasks in Listing B-2! Nevertheless, when Boot composes tasks, it expects handlers to receive and return fileset records Therefore, to convey your data across tasks, you sneakily added it to the fileset record using (merge fileset {:thing thing :pluralize pluralize}) Although that covers the basic concept of a middleware factory, you’ll need to learn a bit more to take full advantage of filesets The mechanics of working with filesets are all explained in the fileset wiki (https://github.com/ boot-clj/boot/wiki/Filesets) In the meantime, I hope this information gave you a good conceptual overview! Next Steps The point of this appendix was to explain the concepts behind Boot However, Boot also has a bunch of other functions, like set-env! and task-options!, that make your programming life easier when you’re actually using it It offers amazing magical features, like providing classpath isolation so you can run multiple projects using one JVM, and letting you add new dependencies to your project without having to restart your REPL If Boot tickles your fancy, check out its README for more information on real-world usage Also, its wiki provides top-notch documentation Boot, the Fancy Clojure Build Framework 289 Fa re w ell! As Semisonic’s hit ’90s song “Closing Time” teaches us, every new beginning comes from some other beginning’s end Congratulations, noble reader, on completing this Clojure journey I hope you’ve found it rewarding, and I hope you’re looking forward to more! And believe me, there’s so much more One of the things I like most about Clojure is that there’s an entire world to explore Logic programming, parsers, type systems—name a fun realm of computer science, and you can investigate it with Clojure I leave you with my humble suggestions of where to go next If you want to get a broad overview of the Clojure ecosystem, check out http://www.clojure-toolbox.com/, which lists hundreds of Clojure projects organized by the problem they solve If you’re interested in web programming, a great place to start is the Luminus framework (http://www.luminusweb.net/) The documentation is excellent, and you’ll have a website running in no time To stay up-to-date with Clojure news, a great resource is Eric Normand’s Clojure Gazzette (http://www.clojuregazette.com/) There’s also the Clojure mailing list, of course (https://groups.google.com/forum/#!forum/ clojure) and the Clojure subreddit is a helpful, friendly place, too (http://www reddit.com/r/clojure) If Twitter is your social media outlet of choice, then @swannodette (David Nolen), @gigasquid (Carin Meier), @puredanger (Alex Miller), @ztellman (Zach Tellman), @bbatsov (Bozhidar Batsov), and @stuartsierra (Stuart Sierra) are your huckleberries You could also follow me, @nonrecursive! Farewell, little teacup, and have fun Clojuring! 292 Farewell! Index Symbols B + (addition operator), 36–37 @, 155, 197 >!! (blocking put), 235–238 !!), 235–238 blocking take (