
July 20th 2016
ORGANIZERS
Charles King

Mike Groseclose

Omer Wazir

Chris Steinmeyer
Introduction to Elixir
-
What is elixir?
-
What is Erlang/OTP?
-
What problems does it solve?
-
When should you use it?
-
Our favorite Parts
-
Resources for learning Elixir/OTP
Topics
What is Elixir?
“Elixir is a dynamic, functional language designed for building scalable and maintainable applications. Elixir leverages the Erlang VM, known for running low-latency, distributed and fault-tolerant systems, while also being successfully used in web development and the embedded software domain.”
Concurrency/Scalability
parent = self()
# Spawns an Elixir process (not an operating system one!)
spawn_link(fn ->
send parent, {:msg, "hello world"}
end)
# Block until the message is received
receive do
{:msg, contents} -> IO.puts contents
end
Immutability
# simple list
[iex(1)> organizers = [:charlie,:chris,:omer,:mike]
[:charlie,:chris,:omer,:mike]
# delete an item
[iex(2)> List.delete(organizers, :charlie)
[:chris, :omer, :mike]
Tooling
$ mix new my_app
$ cd my_app
$ mix test
.
Finished in 0.04 seconds (0.04s on load, 0.00s on tests)
1 tests, 0 failures
$ iex
Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
iex> c "my_file.ex" # Compiles a file
iex> t Enum # Prints types defined in the module Enum
iex> h IEx.pry # Prints the documentation for IEx pry functionality
iex> i "Hello, World" # Prints information about the given data type
Metaprogramming
# Quoting
iex> quote do: sum(1, 2, 3)
# Elixir AST
{:sum, [], [1, 2, 3]}
# Unquoting
iex> number = 13
iex> Macro.to_string(quote do: 11 + number)
"11 + number"
iex> number = 13
iex> Macro.to_string(quote do: 11 + unquote(number))
"11 + 13"
What is Erlang/OTP
Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified bug-ridden slow implementation of half of Erlang"
Rober Virding
-
Erlang was built in 1986 to solve Ericsson's software problems
-
Erlang is a general-purpose programming language and runtime environment. Erlang has built-in support for concurrency, distribution and fault tolerance
-
Erlang runs on a VM called BEAM
OTP - Open Telecom Platform
-
Set of middleware, tools and libraries to help you write resilient code
📽🎞 Erlang: The Movie 📞☎️🍿
What problems does it solve?
Fast for Computers
Fast for Humans
Python
Ruby
JavaScript
C
C++
Elixir
Go
Rust
Java
Erlang
“Elixir is optimized for developer happiness” – via @mwoods79
Created by active Ruby contributor Jose Valim
When should you use it?
-
Having trouble scaling your Ruby application
-
To easily use more than one CPU core (shame on NodeJS)
-
Want to embrace functional programming, with friendly semantics
Our favorite parts
-
Charlie - Processes
-
Mike - Pattern Matching
-
Chris - Umbrella Projects
-
Omer - Streams & Flows
Processes - Charlie
"Processes are isolated from each other, run concurrent to one another and communicate via message passing"
"...not be confused with operating system processes. Processes in Elixir are extremely lightweight in terms of memory and CPU... ...not uncommon to have tens or even hundreds of thousands of processes running simultaneously."
iex> pid = spawn fn -> 1 + 2 end
#PID<0.44.0>
iex> Process.alive?(pid)
false
Processes - Contrived Example
Real world example
Elixir Supervisor
Elixir Processes running NodeJS
http request
html
Streams & Flows - Omer
Streams are composable, lazy enumerables. Any enumerable that generates items one by one during enumeration is called a stream. A stream will not consume or output an item until a regular Enum asks.
In Elixir the Enum module is eager, always consuming an entire collection and often resulting in another collection. Piped enumerable operations create intermediary collections.
Enums Example
iex(1)> organizers = ["Charlie","Chris","Mike","Omer"]
iex(2)> Enum.with_index(organizers)
[{"Charlie", 0}, {"Chris", 1}, {"Mike", 2}, {"Omer", 3}]
iex(3)> organizers |>
...(3)> Enum.with |>
...(3)> Enum.each( fn(organizer, index) ->
...(3)> IO.puts "#{index + 1}. #{organizer}"
...(3)> end)
1. Charlie
2. Chris
3. Mike
4. Omer
Using the Enum module creates intermediary collections
Streams Example
iex(1)> organizers = ["Charlie","Chris","Mike","Omer"]
iex(2)> Stream.with_index(organizers)
#Stream<[enum: ["Charlie", "Chris", "Mike", "Omer"],
funs: [#Function<62.89908360/1 in Stream.with_index/2>]]>
iex(3)> organizers |>
...(3)> Stream.with |>
...(3)> Enum.each( fn(organizer, index) ->
...(3)> IO.puts "#{index + 1}. #{organizer}"
...(3)> end)
1. Charlie
2. Chris
3. Mike
4. Omer
def getWords(path) do
File.stream!(path)
|> Stream.flat_map(&String.split(&1, " "))
|> Enum.reduce(%{}, fn word, acc ->
Map.update(acc, word, 1,& &1 + 1)
end)
|> Enum.to_list()
end
Using Stream.with_index creates a recipe of computation - nothing is evaluated until Enum.each is called
Concurrency with GenStage.Flow
GenStage.Flow executes computation stages in parallel
[file stream] # Flow.from_enumerable/1 (producer)
| |
[M1] [M2] # Flow.flat_map/2 (producer-consumer)
|\ /|
| \/ |
|/ \ |
[R1] [R2] # Flow.reduce/3 (consumer)
M1 & M2 stages receive lines and break them into words
M1 - ["roses", "are", "red"]
M2 - ["violets", "are", "blue"]
Words are consistently routed to R1 or R2 regardless of origin
R1 - ["roses", "are", "red", "are"]
R2 - ["violets", "blue"]
Results of reduced stages
R1 - %{"roses" => 1, "are" => 2, "red" => 1}
R2 - %{"violets" => 1, "blue" => 1}
def getWords(path) do
File.stream!(path)
|> Enum.flat_map(&String.split(&1, " "))
|> Enum.reduce(%{}, fn word, acc ->
Map.update(acc, word, 1,& &1 + 1)
end)
|> Enum.to_list()
end
def getWords(path) do
File.stream!(path)
|> Stream.flat_map(&String.split(&1, " "))
|> Enum.reduce(%{}, fn word, acc ->
Map.update(acc, word, 1,& &1 + 1)
end)
|> Enum.to_list()
end
alias Experimental.GenStage.Flow
def getWords(path) do
File.stream!(path)
|> Flow.from_enumerable()
|> Flow.flat_map(&String.split(&1, " "))
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, acc ->
Map.update(acc, word, 1, & &1+ 1)
end)
|> Enum.to_list()
end
Word count performance in microseconds reading a 12 megabyte text file

Pattern Matching - Mike
=
the match operator
Basic Matching

1 = x because the left hand matches the right hand.
What happens if we try 2 = x ?
Basic Matching

The left hand side does not match the right hand side, so an error is thrown.
Pattern Matching Lists

OK, so how is this different from destructuring assignment?
Pattern Matching Lists

Left hand side can contain values 😱
Pattern Matching Lists

As we'd expect, a match error will occur when a match can't be made.
Pattern Matching Structs

Structs are extensions built on top of maps that provide compile-time checks and default values.
Pattern Matching Structs (Continued)

Let's match against a user struct based on the User.count matching 1
Control-flow Structures

case allows us to compare a value against many patterns until we find a matching one
Putting It All Together
Let's assume we have soft-deletable Users.
Let's find a User (if they are not deleted).
Putting It All Together

The wrong way.
Putting It All Together

Better.
Putting It All Together

👍
Umbrella Projects
☂️
What is an umbrella project?
A project that contains multiple applications.

What are the benefits of umbrella projects over traditional projects?
Umbrella apps offer a cleaner code hierarchy and easier/cleaner tooling

Can utilize GenServer for process supervision

Like a monolith, but totally not!

Like microservices, but totally not!

Greater application flexibility

Resources for learning Elixir
Elixir Language website

Elixir School

Books
Programming Elixir 1.2 by Dave Thomas
Elixir in Action by Saša Jurić
Introducing Elixir by Simon St. Laurent, J. David Eisenberg
The Little Elixir and OTP Guidebook by Benjamin Tan Wei Hao
Erlang books (Great for learning OTP too)
Learn You Some Erlang for great good! by Frederic Trottier-Hebert
Introducing Erlang by Simon St. Laurent
Designing for Scalability with Erlang/OTP by Francesco Cesarini, Steve Vinoski
Programming exercises
-
Exercism.io
-
Codewars.com
-
reddit.com/r/dailyprogrammer
-
Études for Elixir
-
cryptopals crypto challenges
Community
https://elixirforum.com
#myelixirstatus on Twitter
Elixir Fountain podcast
Elixir on Slack - https://elixir-slackin.herokuapp.com/.
Useful articles, videos and repos
-
Elixir source code on Github
-
Erlang Solutions YouTube channel
-
Riak and Erlang/OTP - The Architecture of Open Source Applications http://www.aosabook.org/en/riak.html
-
For large OTP apps see RabbitMQ or Riak
Elixir Introduction
By Charles King
Elixir Introduction
- 908