Mastering Elixir - Andre Albuquerque - E-Book

Mastering Elixir E-Book

André Albuquerque

0,0
40,81 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

Leverage the power of Elixir programming language to solve practical problems associated with scalability, concurrency, fault tolerance, and high availability.




Key Features



  • Enhance your Elixir programming skills using its powerful tools and abstractions


  • Discover how to develop a full-fledged file server


  • Understand how to use Phoenix to create a web interface for your application.



Book Description



Running concurrent, fault-tolerant applications that scale is a very demanding responsibility. After learning the abstractions that Elixir gives us, developers are able to build such applications with inconceivable low effort. There is a big gap between playing around with Elixir and running it in production, serving live requests. This book will help you fll this gap by going into detail on several aspects of how Elixir works and showing concrete examples of how to apply the concepts learned to a fully fledged application. In this book, you will learn how to build a rock-solid application, beginning by using Mix to create a new project. Then you will learn how the use of Erlang's OTP, along with the Elixir abstractions that run on top of it (such as GenServer and GenStage), that allow you to build applications that are easy to parallelize and distribute. You will also master supervisors (and supervision trees), and comprehend how they are the basis for building fault-tolerant applications. Then you will use Phoenix to create a web interface for your application. Upon fnishing implementation, you will learn how to take your application to the cloud, using Kubernetes to automatically deploy, scale, and manage it. Last, but not least, you will keep your peace of mind by learning how to thoroughly test and then monitor your application.




What you will learn



  • Use Elixir tools, including IEx and Mix


  • Find out how an Elixir project is structured and how to create umbrella applications


  • Discover the power of supervision trees, the basis for fault-tolerance


  • Create a Domain-Specifc Language (DSL) that abstracts complexity


  • Create a blazing-fast web interface for your application with Phoenix


  • Set up an automatic deployment process for the cloud


  • Monitor your application and be warned if anything unexpected happens



Who this book is for



Mastering Elixir is for you if you have experience in Elixir programming and want to take it to the next level. This Elixir book shows you how to build, deploy, and maintain robust applications, allowing you to go from tinkering with Elixir on side projects to using it in a live environment. However, no prior knowledge of Elixir is required to enjoy the complex topics covered in the book.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB

Seitenzahl: 753

Veröffentlichungsjahr: 2018

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Mastering Elixir

 

 

 

 

 

 

 

 

 

 

 

Build and scale concurrent, distributed, and fault-tolerant applications

 

 

 

 

 

 

 

 

 

André Albuquerque Daniel Caixinha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BIRMINGHAM - MUMBAI

Mastering Elixir

Copyright © 2018 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the authors, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

Commissioning Editor: Richa TripathiAcquisition Editor: Sandeep MishraContent Development Editor: Anugraha ArunagiriTechnical Editor: Jash BavishiCopy Editor: Muktikant GarimellaProject Coordinator: Ulhas KambaliProofreader: Safis Editing Indexer: Pratik ShirodkarGraphics: Tania DuttaProduction Coordinator: Shantanu Zagade

First published: July 2018

Production reference: 1280718

Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.

ISBN 978-1-78847-267-8

www.packtpub.com

 

To Ana and José

–André Albuquerque

To Raquel and Gabriel

–Daniel Caixinha
 
mapt.io

Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.

Why subscribe?

Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals

Improve your learning with Skill Plans built especially for you

Get a free eBook or video every month

Mapt is fully searchable

Copy and paste, print, and bookmark content

PacktPub.com

Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.

At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.

Contributors

About the authors

André Albuquerque is a software engineer at Onfido, after working in the banking industry for seven years. He has a master's degree from Instituto Superior Técnico in distributed systems and software engineering, and, during his banking detour, he obtained a master's degree in economics. He is currently developing Onfido's microservices using Elixir and Ruby, learning every day about how applications can score and scale if we apply the correct tools and sound coding practices from the get-go. In his time off, he loves to build his own keyboards, play basketball, and spend time with his wife and son.

Thank you, Caixinha, for being crazy enough to embark on this journey with me, and thank you Paulo, for being the kind of mentor that I could only hope to find one day. To all my Onfido colleagues, it's a pleasure to grow with you everyday.This book wouldn't have been possible without the love and support of my family and friends.Ana and José, I am blessed to have you in my life.

 

 

 

Daniel Caixinha is a software engineer at Onfido, where he is using Elixir to build resilient systems that can also handle the high growth of the business. After graduating from Instituto Superior Técnico, he joined the startup world, mainly using Ruby, but also got the chance to play around with Elixir. Upon joining Onfido, he got the chance to take Elixir more seriously, which made him fall in love with functional programming in general, and Elixir in particular. Besides building Elixir applications, he is fostering the use of Elixir, being also a member of the Lisbon Elixir meetup.

First and foremost, this book is dedicated to my soulmate, Raquel, and my son, Gabriel. Without your love, this book wouldn't have been possible. I would also like to thank Onfido in general, but two individuals in particular: André, for being in the trenches with me, and Paulo, who fooled me well into believing I could write a book. Last, but definitely not least, I want to thank my parents for always supporting me to be better.

About the reviewer

Paulo A Pereira is a senior software engineer. He fell in love with Elixir and has a passion for exploring new technologies and keeping himself up to date with the industry's developments.

He previously worked as a consultant and lead developer for Mediadigital, implementing Grails and Rails solutions, and is currently working at Onfido Background Checks, a London-based tech start-up that is proving to be a key player in the background checking industry

 

 

 

 

 

 

 

 

Packt is searching for authors like you

If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.

Table of Contents

Title Page

Copyright and Credits

Mastering Elixir

Dedication

Packt Upsell

Why subscribe?

PacktPub.com

Contributors

About the authors

About the reviewer

Packt is searching for authors like you

Preface

Who this book is for

What this book covers

To get the most out of this book

Download the example code files

Conventions used

Get in touch

Reviews

Preparing for the Journey Ahead

Why functional programming?

Elixir and Erlang

Elixir's data types

Integers

Floats

Atoms

Booleans

Tuples

Lists

Maps

Binaries

Strings and charlists

Other types

Keyword lists

Ranges

MapSets

Pattern matching

Pattern matching on tuples

Pattern matching on lists

Pattern matching on maps

Pattern matching on binaries and strings

Functions and Modules

Anonymous functions

Modules and Named Functions

Module attributes, directives, and uses

Working with collections

Looping through recursion

Eager processing with the Enum module

Comprehensions

Lazy processing with the stream module

Control flow

if and unless

cond

case

with

Exceptions

Typespecs and behaviours

Typespecs

Dialyzer

Behaviours

Protocols

Structs

Bringing structs and protocols together

Tooling and ecosystems

IEx

Mix

ExUnit

Erlang interoperability

Summary

Innards of an Elixir Project

Elixir applications

Elixir project structure

Project dependencies

Umbrella projects

ElixirDrip – our showcase application

Using behaviours

Viewing cross references with xref

Adopting a consistent coding style

Summary

Processes – The Bedrock of Concurrency and Fault Tolerance

Inside the BEAM

Working with processes

Creating processes

Message passing between processes

Building a cache worker

Detecting errors by linking and monitoring processes

Using links

Using monitors

Recovering from errors with supervisors and supervision trees

Defining and starting a supervisor

Streamlined child specs

Starting children at runtime using dynamic supervisors

Minimizing error effects with supervision trees

Summary

Powered by Erlang/OTP

GenServer

GenServer at your service

Implementing a CacheWorker with GenServer

Agent

Task

Parallel tasks

Using (D)ETS

Disk-based ETS

Registry

Summary

Demand-Driven Processing

GenStage

The upload pipeline

The notifier stage

The RemoteStorage stage

The Encryption stage

The Starter stage

The download pipeline

The Notifier stage

The Encryption stage

The RemoteStorage stage

The Starter stage

Final remarks

Flow

Sample data

Lazy queries

Disk-usage rank query

Summary

Metaprogramming – Code That Writes Itself

The abstract syntax tree

Tinkering with macros

Hygienic accesses

Famous (un)quotes

Macros – a silver bullet?

Extending modules

Using the use and __using__/1 macros

Creating a domain-specific language

Registering module attributes

Collecting a list of pipeline steps

Generating worker specs and subscription options

Producer stage

ProducerConsumer and Consumer stages

Collecting the pipeline worker specs

Defining the supervisor functions

Streamlining GenStage modules

Simpler pipeline producers

Simpler pipeline (producer) consumers

Macros cheat sheet

Summary

Persisting Data Using Ecto

Connecting to the database

Schemas and migrations

Schemas

Custom field types

Users or media owners?

Schema or not – that is the question

Migrations

Relationships

Changesets

Media

Users

Media ownership

Constraints

Queries

Media folder queries

Loading schemas and their associations

Queries with raw SQL

Finding top users with aggregates

Summary

Phoenix – A Flying Web Framework

The Plug specification

Creating a module plug

Creating a function plug

Routing requests

Handling requests in a controller

Rendering views

Layouts

Authenticating users

Implementing a JSON API

Authenticating users in the API

Interactive applications using channels

Preparing the server

Joining channels on the client

Exchanging events

Authenticating socket connections

Tracking users statuses using Presence

Summary

Finding Zen through Testing

Unit testing

Testing functions without side-effects

Testing functions with side-effects

Creating mocks with Mox

Testing interactions with the repository separately

Testing the documentation

Integration testing

Testing Phoenix Channels

Testing macros

Property-based testing

Summary

Deploying to the Cloud

Releasing with Distillery

Configuring the release

Interpolating environment variables

Creating the release

Creating a custom release task

Containerizing our application

Creating a development container

Orchestrating more than one container

Composing the deployment containers

Deploying to Kubernetes

Configuring the cloud database

Creating a namespace

Creating secrets

Publishing the production image

Deploying your first pod

Creating a Kubernetes job

Exposing your pods to the world

Continuous deployment with Travis CI

Connecting the deployed Elixir nodes

Testing the connected nodes

Summary

Keeping an Eye on Your Processes

Collecting metrics

Exposing Prometheus metrics

Creating custom Prometheus metrics

Local Prometheus server

Deploying Prometheus in Kubernetes

Calculating percentiles

Setting Grafana variables

A window to your nodes

Connecting to a containerized node

Connecting to an Erlang node running in Kubernetes

Using a remote shell

Inspecting application behavior

Profiling with the fprof profiler

Tracing with the :dbg module

Summary

Other Books You May Enjoy

Leave a review - let other readers know what you think

Preface

Running scalable, concurrent, and fault-tolerant applications is a demanding endeavor. After learning the abstractions that Elixir offers, developersareable to build such applications effortlessly. That being said, there is a big gap between playing around with Elixir and running it in production and serving live requests. Mastering Elixir helps you to fill thisvery gap, and it not only goes into detail about how Elixir works, but also guides you to putthe learned conceptsto good use with the help of concrete examples.

In this book, you will learn how to build a rock solid application, beginning by using Mix to create a new project. You will then explore how to use Erlang’s OTP as well as the Elixir abstractions thatare builton top of it, allowing you to build applications that are easy to parallelize and distribute.Having got to grips with the basics,you will master Supervisors and comprehend how they are the basis for building fault-tolerant applications.In addition to this,you will understand how to use Phoenix in order to create a web interface for your application.

Upon finishing implementation,you will study how to thoroughly test and monitor the developed file server.Toward the end,you will learn how to takethisapplication to the cloud, using Kubernetes to automatically deploy, scale, and manage it.

Who this book is for

Mastering Elixir is for you if you’re a programmer who has some experience in using Elixir and want to take it to the next level. This comprehensive guide shows you how to build, deploy, and maintain robust applications, allowing you to go from tinkering with Elixir on side projects to using it in a live environment. However, no prior knowledge of Elixir is required to enjoy the complex topics covered in the book.

What this book covers

Chapter 1, Preparing for the Journey Ahead, starts our odyssey by introducing Elixir. It starts by covering the data types of Elixir and how pattern matching works, moving on to then explore how to create modules and functions, while also seeing, among other things, how to work with collections and use control flow in Elixir. After reading this chapter, you will be familiar with Elixir's syntax, and how to use it to write some simple functions.

Chapter 2, Innards of an Elixir Project, kicks off by analyzing what makes an Elixir application and what an Elixir project is. It then examines how to use the Mix tool to create projects and manage their dependencies. It's here that we'll create an umbrella project for the ElixirDrip application that will be developed throughout this book.

Chapter 3, Processes – The Bedrock for Concurrency and Fault-tolerance, starts by exploring how the BEAM VM works and its concurrency model, the actor model. Then, it shows how to create and work with processes in Elixir, building a piece of the ElixirDrip application as an example. This chapter also explores how to link and monitor processes, and how Supervisors build on top of this to detect crashing processes. Finally, this chapter explores how we can group Supervisors to create supervision trees, which enable the creation of fault-tolerant applications.

Chapter 4, Powered by Erlang/OTP, introduces OTP and examines both the battle-tested OTP abstractions that Elixir inherited from Erlang, such as GenServer and Erlang Term Storage, and the new Agent, Task and Registry abstractions that Elixir brought to life. Each abstraction is put to good use by implementing a media cache, a text search function, and a search results cache.

Chapter 5, Demand-Driven Processing, goes a long way to explain how the GenStage and Flow abstractions introduced by Elixir let the developer process data using a demand-driven paradigm. Instead of processing data as fast as possible to match the rate at which data is produced, this approach turns the problem on its head and forces the producer to inject new data into the pipeline at a rate controlled by the data consumers. It's in this chapter that the upload and download pipelines of the ElixirDrip application are developed.

Chapter 6, Metaprogramming–Code that Writes Itself, unveils the constructs that allow the developer to easily control what happens in compile time, by writing regular Elixir code that produces more code. The chapter starts by iterating on a macro whose purpose is to measure the time a function takes to execute, and ends by implementing a Domain-Specific language which significantly simplifies the media upload and download pipelines defined in the previous chapter.

Chapter 7, Persisting Data Using Ecto, explores how to work with databases. It starts by explaining how to connect an application to a database and how database structure changes can be applied as migrations. It then examines how to create and enforce table relations and how to use changesets to persist and update data. In the end, different ways to query the database are analyzed.

Chapter 8, Phoenix: A Flying Web Framework, introduces the Phoenix framework and explains how to use it to add a web layer to our ElixirDrip application. The chapter begins by the conventional topics, such as routers, controllers, and views, but toward the end, also explores more progressive concepts, such as building a JSON API or using Phoenix Channels.

Chapter 9, Find Zen through Testing, dives into different kinds of testing. It begins with unit and integration testing, and goes on to explore more elaborate topics, such as how to test macros and Phoenix components, and also how to write property tests.

Chapter 10, Deploy on the Cloud, takes the ElixirDrip application running to its live environment, storing media from real users. This chapter starts by explaining how to use Distillery to package the application in an efficient way and then introduces the concept of application containerization and how it suits the development and deployment phases of our application. The last half of the chapter examines how to deploy the application to a Kubernetes cluster and,ultimately, how to automate this process by using a continuous integration service.

Chapter 11, Keeping an Eye on Your Processes, teaches you how to monitor your application so that you can ensure that your application is working as it should. You will begin by learning how to collect metrics from your application. Then, we will teach you how to use an Erlang tool, called Observer, which allows us to tap into what is going on inside the BEAM virtual machine. You will learn how to get statistics from the BEAM (such as CPU and memory utilization), as well as from the state of each process inside your application. Lastly, we’ll look at how to inspect our application and check what’s happening under the hood. You will learn how to investigate a bottleneck by profiling our ElixirDrip application, while also checking how to use Erlang’s standard library to trace calls to a certain process.

To get the most out of this book

As mentioned earlier, no prior knowledge of Elixir is required to read this book. In the initial chapters, we provide an introduction to Elixir, covering all the necessary concepts to be able to follow the more advanced topics explored later in the book.

To get the most out of this book we recommend that you follow along each chapter, by building and running the application we will develop in this book. To build this application, we have used free and open source software as much as possible. When this was not possible, we have used software with long trial periods, so that you can build and run the application on your own.

Download the example code files

You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.

You can download the code files by following these steps:

Log in or register at

www.packtpub.com

.

Select the

SUPPORT

tab.

Click on

Code Downloads & Errata

.

Enter the name of the book in the

Search

box and follow the onscreen instructions.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

WinRAR/7-Zip for Windows

Zipeg/iZip/UnRarX for Mac

7-Zip/PeaZip for Linux

The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Mastering-Elixir. In case there's an update to the code, it will be updated on the existing GitHub repository.

We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!

 

Conventions used

There are a number of text conventions used throughout this book.

CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "In Elixir, you create a process by calling the Kernel.spawn/1 function".

A block of code is set as follows:

IO.puts("Hello, World!")

Any command-line input or output is written as follows:

$ touch hello_world.ex

Bold: Indicates a new term, an important word, or words that you see on screen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Select elixir from the Processes tab."

Warnings or important notes appear like this.
Tips and tricks appear like this.

Get in touch

Feedback from our readers is always welcome.

General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].

Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.

Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.

Reviews

Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!

For more information about Packt, please visit packtpub.com.

Preparing for the Journey Ahead

Welcome to this incredible journey! This is the beginning of an odyssey that will take you through the many features of Elixir, and how to use them to build, test, deploy, and maintain applications. This journey may require some shifting of your mindset and how you think about programming (and problem-solving in general) if you're not already familiar with functional programming.

Before diving into this book, we want to point out that this introductory chapter is deliberately short. Although we'll be introducing the language, its tooling, and its ecosystem, this won't be a complete reference guide. Elixir treats documentation as a first-class citizen, and this is shown in the incredible documentation of its modules and functions. Hence, we decided to teach you how to search for what you need, and target on the core concept of book–building an Elixir application. We think that this pragmatic approach is the one that delivers the most value to you, as you'll be able to follow an application right from its inception and into its production, including its deployment and monitoring, which are sometimes overlooked.

In this chapter, we will cover the following topics:

Data types in Elixir

Working with pattern matching and how to apply it to various types

Working with functions and bundling them in modules

Working with collections

Using classic control-flow constructs (such as

case

)

Using typespecs on your functions

Creating behaviours, and adopting them in other modules

Using protocols to make our functions polymorphic

Some of the most useful tools that ship with Elixir

Calling Erlang libraries directly

Interacting with operating system processes through ports

Why functional programming?

Coming from an object-oriented background ourselves, we can't emphasize enough how valuable this shift is. Adopting the functional programming paradigm brings along some benefits, such as the following:

The data-transformation flow becomes more evident. This is in contrast with what usually happens in object-oriented programming, where objects strive to encapsulate the data; in functional programming, we mutate data using functions. This makes the transformations that are applied to the data explicit, which in turn makes the applications written this way easier to understand.

Functions are (mostly) side-effect-free. With immutable data, you can be sure that the value of a certain variable you hold a reference to will remain the same, since if another function or process wants to change it, it has to create a copy first—and operate on that copy. This makes code much easier to analyze and comprehend, since you can rest assured that your variables will remain as you expect. However, note that since Elixir isn't a pure functional language, your code can still have side effects. For instance, if a function writes to a file, it creates a side effect.

Programs can be parallelized easily. Coming out as an added bonus of immutability, it's usually very simple to parallelize this type of program, since there is no shared state.

One possible disadvantage of having immutable data is that you can incur a performance penalty, as each time you need to change something, you must make a copy of it. This greatly depends on the implementation, and while this concern is generally valid, Elixir employs clever techniques when compiling your code to minimize this effect. For instance, in certain conditions, Elixir can just point to existing variables when creating new ones, as it knows all variables are immutable and will never change.

If you're overwhelmed with all this functional programming jargon, lie down and relax, as we will explore these concepts in greater detail throughout this book.

Elixir and Erlang

Elixir, created by José Valim, runs on the Erlang VM (also known as BEAM). Erlang, developed at Ericsson more than 30 years ago, was created to improve the reliability and scalability of the company's telecom systems. Nowadays, it is used in a number of different settings, from database systems to chat applications. Erlang has fault-tolerance and distribution baked into its design, and is famous for running systems with nine nines of reliability.

Erlang's runtime is natively distributed, given that it was designed to be deployed on multiple telecom switches simultaneously. Programs running on the Erlang VM can take advantage of this by easily distributing an application across multiple nodes, but also across multiple CPUs—since multiple cores is just a specific case of a distributed system. This is an incredible selling point of the Erlang VM (and thus of Elixir), since in today's setting CPUs are not getting much faster, and we're instead seeing CPUs with an increasing number of cores coming out.

In this opening chapter, we will be introducing Elixir. Beginning with its data types, we will also look at pattern matching, anonymous and named functions, modules, and some control-flow constructs. Then, we will see how to work with collections, and then we will briefly touch on behaviours and protocols. The chapter will end with an overview of the incredible tooling Elixir provides, along with some ways to exploit the existing interoperability between Elixir and Erlang.

Elixir's data types

We will now describe Elixir's data types, which extend upon Erlang's data types. Elixir is a dynamic programming language. Consequently, you don't declare the type of each variable—it depends on the value it holds at each moment.

To improve the learning experience, we'll be providing some examples along the way. For now, we'll just use Elixir's REPL, IEx (short for Interactive Elixir). To start an IEx session, you must have Elixir installed on your machine. Elixir has an official page with instructions on how to do this if you don't have it installed,  whether using package managers, the precompiled version, or compiling from the source yourself:

http://elixir-lang.github.io/install.html 

We will not dive into the memory usage of each type in Elixir. If you're curious about this, the official Erlang documentation contains detailed information: http://erlang.org/doc/efficiency_guide/advanced.html.

Provided that you have Elixir already installed on your machine, type iex on your terminal to start a new IEx session. With this, you can run the examples present in this chapter in your machine. Note that your default iex  prompt contains a number in between parenthesis, which represents the number of expressions you've entered in the current session, such as iex>(1). To declutter the output, in our examples, we've removed this number.

We'll be exploring IEx in greater detail toward the end of this chapter, in the Tooling and ecosystems section. Throughout the following subsections, we'll be mentioning some built-in modules in Elixir. We'll explore what modules are in the Functions and modules section—for now, it's enough to know that a module is a collection of functions.

Whenever you're done with your IEx session, you can either press Ctrl + C twice or Ctrl + \. This will kill the operating system process that's running the Erlang runtime (along with all background jobs). Alternatively, you can stop the system in a more polite way by entering System.halt in the shell.

Integers

This type contains, as you would expect, numbers that can be written without a fractional component. The size of integers adjusts dynamically according to its magnitude—you don't have to worry about this: an integer will simply occupy more words in memory as it grows. Here's some basic arithmetic with integers:

iex> 25 + 8

33

To improve the readability of the code, you can also use underscores in between the digits of an integer, as shown here:

iex> 1_000_000 - 500_000

500000

Besides decimal, Elixir also supports integers written in binary, octal, and hexadecimal (using 0b, 0o, and 0x, respectively):

iex> 0b10001

17

iex> 0o21

17

iex> 0x11

17

Floats

In Elixir, floats are written with a decimal point, with digits before and after it, meaning that .1 is not a valid float in Elixir (as it is, for instance, in JavaScript). In Elixir, you have to be explicit and write the leading 0—so in this case, you'd write 0.1. Here's an example of the multiplication of two floats:

iex> 0.1 * 0.5

0.05

You can also write floats using the exponent notation, as shown:

iex> 0.1e3

100.0

Floats are represented in IEEE 754 double precision, which yields between 15 to 17 significant decimal digits. As usual, you should take care when comparing floats for equality.

Beware that the division operator (/) always returns a float, even if the result of the division could be an integer:iex> 4/22.0 If you want to circumvent this behavior, use the auto-imported div function from the Kernel module. Also, if you want to get the remainder of a division, use the rem function.

Atoms

Atoms are a constant, whose value is its own name. They are always prefixed with a leading colon (:), followed by alphanumeric characters (and possibly _ or @). They may terminate with an exclamation or a question mark. Atoms are similar to enumerations in C and symbols in Ruby. Here are some examples of atoms:

iex> :ok

:ok

iex> :error

:error

iex> :some_descriptive_name!

:some_descriptive_name!

iex> :value@start

:value@start

You can create atoms with arbitrary characters with the following syntax:

iex> :"Atom name with arbitrary characters#$%^"

:"Atom name with arbitrary characters#$%^"

As with all data structures in Elixir, atoms can't be modified after their creation. Furthermore, they are not garbage-collected. Atoms are kept in the atom table, and upon compilation, their value is replaced by a reference to their entry on this table. This makes comparing atoms very efficient. As you'll learn throughout this book, this is one of the major use cases for atoms in Elixir, as we are constantly matching the return of a function against a certain expected atom.

Since atoms are not garbage collected, don't create atoms dynamically from sources you can't control, as you can very easily use up all of the space allocated for the atom table. For instance, if you're parsing a JSON response and creating a map out of it, don't use atoms for its keys—use strings instead (both of these types, maps and strings, will be described later in this chapter).

Lists

Lists are created by wrapping the elements we want inside it with square brackets ([ and ]), separating the values with commas. Internally, lists are implemented as singly linked lists, meaning that accessing the elements of a list is a O(n) operation. Lists aren't stored contiguously in memory as arrays in other languages. As with tuples, list elements can be of any type:

iex> [1, :an_atom, 0.5]

[1, :an_atom, 0.5]

We have the ++ and -- operators that are exclusive to lists, and serve to concatenate and subtract lists, respectively:

iex> [0, 1, 1] ++ [2, 3, 5]

[0, 1, 1, 2, 3, 5]

iex> [0, 1, 1] -- [1, 2, 3]

[0, 1]

To check whether a certain element is present in a list, you can use the in operator:

iex> 1 in [0, 1, 1, 2, 3, 5]

true

iex> 99 in [0, 1, 1, 2, 3, 5]

false

To get the head of a list, we use the hd function, whereas to get the tail of a list, we use the tl function:

iex> hd([0, 1, 1, 2, 3, 5])

0

iex> tl([0, 1, 1, 2, 3, 5])

[1, 1, 2, 3, 5]

Notice that the semantic of tail here is the list without its head (which is also a list), and not the last element of a list. We'll be exploring this concept in more depth, along with some more examples on how to work with lists, in the Working with collections section. For reference, you can find a detailed list of operations you can make on lists at https://hexdocs.pm/elixir/List.html.

Appending to a list is a O(n) operation, as we need to traverse the whole list. Prepending to a list is O(1). To prepend an element to a list, you can use the following syntax: [new_element | list].

Binaries

A binary is group of consecutive bytes. You create them by surrounding the byte sequence with << and >>. Here we are creating a two-byte binary:

iex> <<5, 10>>

<<5, 10>>

In the decimal base, a byte can only contain values up to 255 (otherwise it overflows). If we want to store values greater that 255, we need to tell the runtime to use more space to store this binary:

iex> <<5, 256>>

<<5, 0>>

iex> <<5, 256::16>>

<<5, 1, 0>>

As you can see, when we specify the size (16 bits in this case) we can see that the output as an extra byte and the overflow didn't occur. The size doesn't have to be a multiple of 8. In that case, a binary is usually called a bitstring.

Most programmers will not handle data at such a low level, so your use of binaries may not be that frequent. However, they're extremely useful in certain scenarios, such as processing the header of a file to find a magic number and identify the file type, or even when dealing with network packets by hand.

Strings and charlists

Strings are binaries with UTF-8 codepoints in them. You create a string with the usual double-quote syntax:

iex> "hey, a string"

"hey, a string"

Charlists are, as the name implies, lists of character codes. You create them using the single-quote syntax:

iex> 'hey, a charlist'

'hey, a charlist'

Since this is just a list, you can use the hd function to get the code for the first character:

iex> hd('hey, a charlist')

104

You can find out the code of a certain character with the ? operator. For instance, to find out the character code of a lowercase d, you'd use ?d.

Both representations support string interpolation:

iex> "two plus two is: #{2+2}"

"two plus two is: 4"

iex> 'four minus one is: #{4-1}'

'four minus one is: 3'

Both representations also support the heredoc notation, which is most commonly used to write documentation. To create it, use three single or double quotes:

iex> """

...> a string with heredoc notation

...> """

"a string with heredoc notation\n"

iex> '''

...> a charlist with heredoc notation

...> '''

'a charlist with heredoc notation\n'

The closing delimiter of a heredoc string/charlist must be on its own line.

Elixir provides sigils as another syntax to declare strings or charlists, which can be handy if you want to include quotes inside your string. You can use ~s to create a string and ~c to create a charlist (their uppercase versions, ~S and ~C, are similar but don't interpolate or escape characters):

iex> ~s(a string created by a sigil)

"a string created by a sigil"

iex> ~c(a charlist created by a sigil)

'a charlist created by a sigil'

There's another sigil that's worth mentioning: ~r, which is used for regular expressions. In the next snippet, we're using the run function from the Regex module to exemplify the usage of the ~r sigil:

iex> Regex.run(~r{str}, "a string")

["str"]

iex> Regex.run(~r{123}, "a string")

nil

You can find the list of supported sigils (and also how to create your own!) at http://elixir-lang.github.io/getting-started/sigils.html.

The convention in the Elixir community is to only use the term string when referring to the double-quote format. This distinction is important, since their implementation is very different. Functions from the String module will only work on the double-quote format. You should always use the double-quote format, unless you're required to use a charlist—which is the case, for instance, when you're using Erlang libraries. You can use the following functions to convert between the two formats:

iex> String.to_charlist("converting to charlist")

'converting to charlist'

iex> List.to_string('converting to string')

"converting to string"

Other types

We'll now succinctly describe some other types. We'll begin with the types that build upon some types we've already described: keyword lists, ranges, mapsets, and IO lists.

Ranges

Ranges, again, similar to what happens in Ruby, represent an interval between two integers. To create a range, we use this:

iex> 17..21

17..21

iex> 19 in 17..21

true

Similar to what we do with a list, we can use the in operator to check whether a number is between the start and the end of a range.

Functions and Modules

Despite not being mentioned in the data types section, functions in Elixir are a type as well–in fact, they are a first-class citizen, as they can be assigned to a variable and passed as arguments to other functions.

As with most functional programming languages, functions are an important type, hence they justify having their own section, away from other built-in types.

We will start by exploring anonymous functions, followed by an explanation of modules and named functions, and then we'll end this section with a quick tour of module attributes and directives.