Introduction to Elixir
Elixir
Elixir is a dynamic, functional language designed for building scalable and maintainable applications.
Elixir is influenced by
Ruby | syntax | intelligent sugar |
---|---|---|
Erlang | semantics | BEAM, concurrency model |
Lisp | extensibility | metaprogramming, macros |
Elixir and Erlang
The syntax is the most obvious difference between Erlang et Elixir but not the only difference.
Both languages shares a common ground: same VM, same OTP library, ... but Elixir also aims to improve some of the Erlang flaws.
The problem
Years ago...
But one day "free lunch is over"
https://en.wikipedia.org/wiki/Herb_Sutter#The_Free_Lunch_Is_Over
Concurrency
Concurrency is the composition of independently executing computations.
Why concurrency?
- Using all cores
- Using all computers
- Solve async problems
Classical solution
- Low level concurrency control
- Shared memory communication
Problems
- Deadlock
- Inanition
- Not using all cores
- Race condition
Low level methods
- Threads
- Mutexes
- Critical sections
Locks
- Difficult to write
- Difficult to reason
- Difficult to mantein
- Difficult to test
High level methods
- CSP
- Actors
- Transactional memory
The actor model
- Carl Hewitt's model for the foundation of computation
- everything is an actor
- actors communicate by messages
- actors can create other actors
- and change behaviour according to messages
- 900 mill. Users
- 19Billion messages in & 40B out per day
- 350.000 msg/sec average
- 2 mill. connections/node
- 50 engineers
Backend for multiplayer videogames
Call of duty black ops, best selling videogame.
"We’re converting our notifications system from Java to Elixir. The Java version used an Actor system and weighed in at around 10,000 lines of code. The new Elixir system has shrunk this to around 1000 lines. The Elixir based system is also faster and more consistent than the Java one and runs on half the number of servers."
Bet365 and Erlang
"Our code base is vastly simplified now, and we have less issues with reliability. We are an incredibly peaky business and we find that at the peak of trading we are able to provide our customer with a much more predictable quality product using Erlang,"
What is Elixir/Erlang good for?
-
Chat servers (WhatsApp, ejabberd)
-
Game servers (Wooga)
-
Web frameworks (Phoenix)
-
Distributed databases (Riak and CouchDB)
-
Real-time bidding servers
-
Long-running services/daemons
-
Command-line applications
Erlang
Agner erlang: was a Danish mathematician, statistician and engineer, who invented the fields of traffic engineering and queueing theory.
Creators of Erlang
Erlang
Erlang the movie
Erlang
- Functional, no mutability
- Actors (message passing)
- Light processes
- Open source since 1998
Elixir
Created by Jose Valim
Why should I care about elixir?
Reasons
-
Superb standard library
-
Added namespaces
-
Added Structs
-
Allowed variable rebinding
-
Added Pipe-operator |>
-
Added polymorphism
-
Added Lisp-style macros
-
Changed syntax
|> — The Pipe Operator
people = DB.find_customers
orders = Orders.for_customers(people)
tax = sales_tax(orders, 2013)
filing = prepare_filing(tax)
|> — The Pipe Operator
prepare_filing(sales_tax(Orders.-
for_customers(DB.find_customers), 2013))
|> — The Pipe Operator
filing = DB.find_customers
|> Orders.for_customers
|> sales_tax(2013)
|> prepare_filing
Pattern matching
iex> a = 1
1
iex> 1 = a
1
iex> { m, n } = { 2, 3 }
{2, 3}
iex> [ e, f, g ] = [ 4, 5, 6 ]
[4, 5, 6]
iex> "Elixir" <> rest = "Elixir Rocks!"
"Elixir Rocks!"
iex> rest
" Rocks!"
iex> [head | tail] = [1, 2, 3]
[1, 2, 3]
iex> head
1
iex> tail
[2, 3]
Recursion and Pattern matching
defmodule Fib do
def fib(0), do: 0
def fib(1), do: 1
def fib(n), do: fib(n-1) + fib(n-2)
end
Recursion and Pattern matching
defmodule MyList do
def sum([], total), do: total
def sum([head | tail], total), do: sum(tail, head+total)
end
MyList.sum([1,2,3,4,5], 0)
Pattern matching
handle_open = fn
({:ok, file}) -> "First line: #{IO.read(file, :line)}"
{_, error} -> "Error: #{:file.format_error(error)}"
end
IO.puts handle_open.(File.open("file.ex"))
Immutability
iex> name = "elixir"
"elixir"
iex> String.capitalize name
"Elixir"
iex> name
"elixir"
“In a functional language, we always transform data. We never modify it in place”
Quote from “Programming Elixir”.
Immutability
m = %{ a: 1, b: 2, c: 3 }
%{a: 1, b: 2, c: 3}
iex> m1 = %{ m | b: "two", c: "three" }
%{a: 1, b: "two", c: "three”}
iex> m2 = %{ m1 | a: "one" }
%{a: "one", b: "two", c: "three"}
Tooling
1. Mix
A task runner. It is used to start servers, install dependencies, run tests,...
2. Hex
Package manager allowing to download Erlang and Elixir packages
3. Iex
Read eval print loop
Hot reload
Nothing to do, just compile and use your new .ex
you don't need to reboot your app,
static typing would have been complicated with this
Observer
> :observer.start
A very useful debug console
Other
Dialyzer: let you do a static analysis
Reltool: tool to make erlang releases
(used by rebar)
Erlang.mk: Alternative to rebar based on a makefile
WombatOAM: commercial product for system supervision
Concurrent Programming
Primitive
OTP
Tasks and Agents
Processes versus threads
- Processes share nothing with each other
- In the vm not the os, like green threads but
- more lightweigth than threads
- more numerous
- more control: stack, heap and gc per process
Message send and message receive are decoupled
- avoids common source of deadlock
- directly supports processes distributed across a network
- supports more complex message handling
- can simulate synchrony through send/receive protocol
Technical requirement | Server A | Server B |
---|---|---|
Http Server | Nginx | Elixir |
Request Processing | Ruby on rails/Node | Elixir |
Long running requests | Go | Elixir |
Server-Wide State | Redis | Elixir |
Persistable data | Redis & Mongo | Elixir |
Background jobs | Cron, bash scripts | Elixir |
Server crash recovery | Upstart | Elixir |
Twilio
Dokku
Thank you
elixir
By gabrielc
elixir
- 512