Programming Elixir ≥ 1.6 Functional |> Concurrent |> Pragmatic |> Fun Dave Thomas The Pragmatic Bookshelf 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 books, screencasts, and audio books can help you and your team create better software and have more fun. Visit us at https://pragprog.com. The team that produced this book includes: Publisher: Andy Hunt VP of Operations: Janet Furlow Managing Editor: Brian MacDonald Supervising Editor: Jacquelyn Carter Copy Editor: Candace Cunningham Indexing: Potomac Indexing, LLC Layout: Gilson Graphics For sales, volume licensing, and support, please contact [email protected]. For international rights, please contact [email protected]. Copyright © 2018 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-68050-299-2 Encoded using the finest acid-free high-entropy binary digits. Book version: P1.0—May 2018 Contents Foreword . . . . . . . . . . . . . . ix A Vain Attempt at a Justification, Take Two . . . . . xi 1. Take the Red Pill . . . . . . . . . . . . 1 Programming Should Be About Transforming Data 1 Installing Elixir 3 Running Elixir 4 Suggestions for Reading the Book 10 Exercises 10 Think Different(ly) 11 Part I — Conventional Programming 2. Pattern Matching . . . . . . . . . . . 15 Assignment: I Do Not Think It Means What You Think It Means. 15 More Complex Matches 16 Ignoring a Value with _ (Underscore) 18 Variables Bind Once (per Match) 18 Another Way of Looking at the Equals Sign 20 3. Immutability . . . . . . . . . . . . 21 You Already Have (Some) Immutable Data 21 Immutable Data Is Known Data 22 Performance Implications of Immutability 23 Coding with Immutable Data 24 4. Elixir Basics . . . . . . . . . . . . . 25 Built-in Types 25 Value Types 26 Contents • iv System Types 28 Collection Types 28 Maps 31 Binaries 32 Dates and Times 33 Names, Source Files, Conventions, Operators, and So On 34 Variable Scope 36 End of the Basics 40 5. Anonymous Functions . . . . . . . . . . 41 Functions and Pattern Matching 42 One Function, Multiple Bodies 43 Functions Can Return Functions 45 Passing Functions as Arguments 47 Functions Are the Core 51 6. Modules and Named Functions . . . . . . . . 53 Compiling a Module 53 The Function’s Body Is a Block 54 Function Calls and Pattern Matching 55 Guard Clauses 58 Default Parameters 60 Private Functions 63 The Amazing Pipe Operator: |> 63 Modules 65 Module Attributes 67 Module Names: Elixir, Erlang, and Atoms 68 Calling a Function in an Erlang Library 69 Finding Libraries 69 7. Lists and Recursion . . . . . . . . . . . 71 Heads and Tails 71 Using Head and Tail to Process a List 72 Using Head and Tail to Build a List 74 Creating a Map Function 75 Reducing a List to a Single Value 76 More Complex List Patterns 78 The List Module in Action 81 Get Friendly with Lists 82 Contents • v 8. Maps, Keyword Lists, Sets, and Structs . . . . . . 83 How to Choose Between Maps, Structs, and Keyword Lists 83 Keyword Lists 84 Maps 84 Pattern Matching and Updating Maps 85 Updating a Map 87 Structs 88 Nested Dictionary Structures 89 Sets 95 With Great Power Comes Great Temptation 95 9. An Aside—What Are Types? . . . . . . . . . 97 10. Processing Collections—Enum and Stream . . . . . 99 Enum—Processing Collections 99 Streams—Lazy Enumerables 103 The Collectable Protocol 110 Comprehensions 111 Moving Past Divinity 114 11. Strings and Binaries . . . . . . . . . . 117 String Literals 117 The Name “strings” 120 Single-Quoted Strings—Lists of Character Codes 121 Binaries 123 Double-Quoted Strings Are Binaries 124 Binaries and Pattern Matching 130 Familiar Yet Strange 132 12. Control Flow . . . . . . . . . . . . 133 if and unless 133 cond 134 case 137 Raising Exceptions 138 Designing with Exceptions 138 Doing More with Less 139 13. Organizing a Project . . . . . . . . . . 141 The Project: Fetch Issues from GitHub 141 Step 1: Use Mix to Create Our New Project 142 Transformation: Parse the Command Line 145 Write Some Basic Tests 146 Contents • vi Refactor: Big Function Alert 149 Transformation: Fetch from GitHub 149 Step 2: Use Libraries 151 Transformation: Convert Response 156 Transformation: Sort Data 158 Transformation: Take First n Items 159 Transformation: Format the Table 160 Step 3: Make a Command-Line Executable 163 Step 4: Add Some Logging 164 Step 5: Create Project Documentation 166 Coding by Transforming Data 167 14. Tooling . . . . . . . . . . . . . 169 Debugging with IEx 169 Testing 173 Code Dependencies 186 Server Monitoring 187 Source-Code Formatting 190 Inevitably, There’s More 193 Part II — Concurrent Programming 15. Working with Multiple Processes . . . . . . . 197 A Simple Process 198 Process Overhead 203 When Processes Die 206 Parallel Map—The “Hello, World” of Erlang 210 A Fibonacci Server 211 Agents—A Teaser 215 Thinking in Processes 216 16. Nodes—The Key to Distributing Services . . . . . 219 Naming Nodes 219 Naming Your Processes 223 Input, Output, PIDs, and Nodes 226 Nodes Are the Basis of Distribution 228 17. OTP: Servers . . . . . . . . . . . . 229 Some OTP Definitions 229 An OTP Server 230 GenServer Callbacks 238 Contents • vii Naming a Process 240 Tidying Up the Interface 240 Making Our Server into a Component 242 18. OTP: Supervisors . . . . . . . . . . . 247 Supervisors and Workers 247 Worker Restart Options 254 Supervisors Are the Heart of Reliability 255 19. A More Complex Example . . . . . . . . . 257 Introduction to Duper 257 The Duper Application 262 But Does It Work? 272 Planning Your Elixir Application 274 Next Up 275 20. OTP: Applications . . . . . . . . . . . 277 This Is Not Your Father’s Application 277 The Application Specification File 278 Turning Our Sequence Program into an OTP Application 278 Supervision Is the Basis of Reliability 281 Releasing Your Code 282 Distillery—The Elixir Release Manager 282 OTP Is Big—Unbelievably Big 292 21. Tasks and Agents . . . . . . . . . . . 293 Tasks 293 Agents 295 A Bigger Example 297 Agents and Tasks, or GenServer? 300 Part III — More Advanced Elixir 22. Macros and Code Evaluation . . . . . . . . 303 Implementing an if Statement 303 Macros Inject Code 304 Using the Representation as Code 307 Using Bindings to Inject Values 312 Macros Are Hygienic 313 Other Ways to Run Code Fragments 314 Macros and Operators 315 Contents • viii Digging Deeper 316 Digging Ridiculously Deep 316 23. Linking Modules: Behavio(u)rs and use . . . . . . 319 Behaviours 319 use and __using__ 322 Putting It Together—Tracing Method Calls 322 Use use 326 24. Protocols—Polymorphic Functions . . . . . . . 329 Defining a Protocol 329 Implementing a Protocol 330 The Available Types 331 Protocols and Structs 332 Built-in Protocols 333 Protocols Are Polymorphism 345 25. More Cool Stuff . . . . . . . . . . . 347 Writing Your Own Sigils 347 Multi-app Umbrella Projects 351 But Wait! There’s More! 354 A1. Exceptions: raise and try, catch and throw . . . . . 355 Raising an Exception 355 catch, exit, and throw 357 Defining Your Own Exceptions 358 Now Ignore This Appendix 359 A2. Type Specifications and Type Checking . . . . . . 361 When Specifications Are Used 361 Specifying a Type 362 Defining New Types 364 Specs for Functions and Callbacks 365 Using Dialyzer 366 Bibliography . . . . . . . . . . . . 373 Index . . . . . . . . . . . . . . 375
Description: