Functional Programming Patterns in Scala and Clojure Write Lean Programs for the JVM
Total Page:16
File Type:pdf, Size:1020Kb
Early Praise for Functional Programming Patterns This book is an absolute gem and should be required reading for anybody looking to transition from OO to FP. It is an extremely well-built safety rope for those crossing the bridge between two very different worlds. Consider this mandatory reading. ➤ Colin Yates, technical team leader at QFI Consulting, LLP This book sticks to the meat and potatoes of what functional programming can do for the object-oriented JVM programmer. The functional patterns are sectioned in the back of the book separate from the functional replacements of the object-oriented patterns, making the book handy reference material. As a Scala programmer, I even picked up some new tricks along the read. ➤ Justin James, developer with Full Stack Apps This book is good for those who have dabbled a bit in Clojure or Scala but are not really comfortable with it; the ideal audience is seasoned OO programmers looking to adopt a functional style, as it gives those programmers a guide for transitioning away from the patterns they are comfortable with. ➤ Rod Hilton, Java developer and PhD candidate at the University of Colorado Functional Programming Patterns in Scala and Clojure Write Lean Programs for the JVM Michael Bevilacqua-Linn The Pragmatic Bookshelf Dallas, Texas • Raleigh, North Carolina 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 The Pragmatic Programmers, LLC was aware of a trademark claim, the designations have been printed in initial capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic Programming, Pragmatic Bookshelf, PragProg and the linking g device are trade- marks of The Pragmatic Programmers, LLC. Every precaution was taken in the preparation of this book. However, the publisher assumes no responsibility for errors or omissions, or for damages that may result from the use of information (including program listings) contained herein. Our Pragmatic courses, workshops, and other products can help you and your team create better software and have more fun. For more information, as well as the latest Pragmatic titles, please visit us at http://pragprog.com. The team that produced this book includes: Fahmida Rashid (editor) Potomac Indexing, LLC (indexer) Molly McBeath (copyeditor) David J Kelly (typesetter) Janet Furlow (producer) Juliet Benda (rights) Ellie Callahan (support) Copyright © 2013 The Pragmatic Programmers, LLC. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. Printed in the United States of America. ISBN-13: 978-1-937785-47-5 Encoded using the finest acid-free high-entropy binary digits. Book version: P1.0—October 2013 Contents Acknowledgments . vii Preface . ix 1. Patterns and Functional Programming . 1 1.1 What Is Functional Programming? 3 1.2 Pattern Glossary 4 2. TinyWeb: Patterns Working Together . 9 2.1 Introducing TinyWeb 9 2.2 TinyWeb in Java 9 2.3 TinyWeb in Scala 20 2.4 TinyWeb in Clojure 28 3. Replacing Object-Oriented Patterns . 39 3.1 Introduction 39 Pattern 1. Replacing Functional Interface 40 Pattern 2. Replacing State-Carrying Functional Interface 47 Pattern 3. Replacing Command 54 Pattern 4. Replacing Builder for Immutable Object 62 Pattern 5. Replacing Iterator 72 Pattern 6. Replacing Template Method 83 Pattern 7. Replacing Strategy 92 Pattern 8. Replacing Null Object 99 Pattern 9. Replacing Decorator 109 Pattern 10. Replacing Visitor 113 Pattern 11. Replacing Dependency Injection 128 4. Functional Patterns . 137 4.1 Introduction 137 Pattern 12. Tail Recursion 138 Pattern 13. Mutual Recursion 146 Contents • vi Pattern 14. Filter-Map-Reduce 155 Pattern 15. Chain of Operations 159 Pattern 16. Function Builder 167 Pattern 17. Memoization 182 Pattern 18. Lazy Sequence 186 Pattern 19. Focused Mutability 196 Pattern 20. Customized Control Flow 206 Pattern 21. Domain-Specific Language 218 5. The End . 229 Bibliography . 231 Index . 233 Acknowledgments I’d like to thank my parents, without whom I would not exist. Thanks also go to my wonderful girlfriend, who put up with many a night and weekend listening to me mutter about code samples, inconsistent tenses, and run-on sentences. This book would have suffered greatly without a great group of technical reviewers. My thanks to Rod Hilton, Michajlo “Mishu” Matijkiw, Venkat Sub- ramaniam, Justin James, Dave Cleaver, Ted Neward, Neal Ford, Richard Minerich, Dustin Campbell, Dave Copeland, Josh Carter, Fred Daoud, and Chris Smith. Finally, I’d like to thank Dave Thomas and Andy Hunt. Their book, The Pragmatic Programmer, is one of the first books I read when I started my career. It made a tremendous impact, and I’ve still got my original dog-eared, fingerprint-covered, bruised and battered copy. In the Pragmatic Bookshelf, they’ve created a publisher that’s truly dedicated to producing high-quality technical books and supporting the authors who write them. report erratum • discuss Preface This book is about patterns and functional programming in Scala and Clojure. It shows how to replace, or greatly simplify, many of the common patterns we use in object-oriented programming, and it introduces some patterns commonly used in the functional world. Used together, these patterns let programmers solve problems faster and in a more concise, declarative style than with object-oriented programming alone. If you’re using Java and want to see how functional programming can help you work more efficiently, or if you’ve started using Scala and Clojure and can’t quite wrap your head around functional problem-solving, this is the book for you. Before we dig in, I’d like to start off with a story. This story is true, though some names have been changed to protect the not-so-innocent. A Tale of Functional Programming by: Michael Bevilacqua-Linn, software firefighter The site isn’t down, but an awful lot of alarms are going off. We trace the problems to changes someone made to a third-party API we use. The changes are causing major data problems on our side; namely, we don’t know what the changes are and we can’t find anyone who can tell us. It also turns out the system that talks to the API uses legacy code, and the only guy who knows how to work on it happens to be away on vacation. This a big system: 500,000-lines-of- Java-and-OSGI big. Support calls are flooding in, lots of them. Expensive support calls from frustrated customers. We need to fix the problem quickly. I start up a Clojure REPL and use it to poke around the problem API. My boss pokes his head into my office. “How’s it going?” he asks. “Working on it,” I say. Ten minutes later, my grandboss pokes his head into my office. “How’s it going?” he asks. “Working on it,” I say. Another ten minutes pass by when my great-grandboss pokes his head into my office. “How’s it going?” he asks. “Working on it,” I say. I get a half hour of silence before the CTO pokes his head into my office. “Working on it,” I say before he opens his mouth. An hour passes, and I figure out what’s changed. I whip up a way to keep the data clean until the legacy developer gets back and can put together a proper fix. I hand my little program off report erratum • discuss Preface • x to the operations team, which gets it up and running in a JVM, somewhere safe. The support calls stop coming in, and everyone relaxes a bit. A week or so later at an all-hands meeting, the great-grandboss thanks me for the Java program I wrote that saved the day. I smile and say, “That wasn’t Java.” The REPL, Clojure’s interactive programming environment, helped a lot in this story. However, lots of languages that aren’t particularly functional have similar interactive programming environments, so that’s not all there is to it. Two of the patterns that we’ll see in this book, Pattern 21, Domain-Specific Language, on page 218, and Pattern 15, Chain of Operations, on page 159, contributed greatly to this story’s happy ending. Earlier on, I had written a small instance of domain-specific language for working with these particular APIs that helped me explore them very quickly even though they’re very large and it was difficult to figure out where the problem might lie. In addition, the powerful data transformation facilities that functional programming relies on, such as the examples we’ll see in Pattern 15, Chain of Operations, on page 159, helped me quickly write code to clean up the mess. How This Book Is Organized We’ll start with an introduction to patterns and how they relate to functional programming. Then we’ll take a look at an extended example, a small web framework called TinyWeb. We’ll first show TinyWeb written using classic object-oriented patterns in Java. We’ll then rewrite it, piece by piece, to a hybrid style that is object oriented and functional, using Scala. We’ll then write in a functional style using Clojure. The TinyWeb extended example serves a few purposes. It will let us see how several of the patterns we cover in this book fit together in a comprehensive manner. We also use it to introduce the basics of Scala and Clojure. Finally, since we’ll transform TinyWeb from Java to Scala and Clojure bit by bit, it gives us a chance to explore how to easily integrate Java code with Scala and Clojure.