I Code Elixir

And So Can YOU!

I'm not even going to pretend to be objective, but I will try to avoid hyperbole

FANBOY/KOOL-AID ALERT

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.

Why Learn Elixir?

Haven't we invented all the languages?

Why Learn Elixir?

  • Not Elixir, but Erlang
  • FB bought for $17Bn w/ 600m+ active users
  • >1Bn active users
  • Millions of connections per server
  • Low 1000's of servers
  • 50 engineers total at FB sale, ~15 on backend
  • Had no Erlang expert experience, but picked it up

Why Learn Elixir?

  • Very early adopters
  • Replaced Rails news aggregation with Elixir
  • 20 servers down to 2 (only need 2 for redundancy)
  • Expanded use of Elixir to power all their notifications
  • They're replacing all Rails apps over time as teams choose to switch

Why Learn Elixir?

  • Trial microservice
  • Implemented Java-based rate limiter service in Elixir 
  • Cut # servers in half
  • Percentile latency: 50th 500µs, 90th 800µs, 99th: 120ms-250ms
  • Old 99th latency: 300ms-1200ms
  • Code went from 10kloc to 1kloc

Why Learn Elixir?

  • Has Erlang's traits (low latency) because it has Erlang's semantics
  • Removes syntax anxiety
  • Focuses on developer happiness
    • Good tooling
    • Value simplicity and correctness over being easy
    • No magic!
  • Great community welcomes new members

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.

Language Basics

Dynamic

  • No static typing in compiler
  • Pattern matching helps
  • Static analysis is available via dialyzer
  • Types are strict
  • Type system can be extended
iex> x = 1
1
iex> 1 = x
1
iex> [a, b, c] = [1, 2, 3]
[1, 2, 3]
iex>; a
1
iex> [head|tail] = [1,2,3]
[1, 2, 3]
iex> head
1
iex> tail
[2, 3]

iex - Interactive Shell

(not just REPL)

iex> 1               # integer
iex> 0x1F            # integer
iex> 1.0             # float
iex> true            # boolean
iex> :atom           # atom / symbol
iex> "elixir"        # string
iex> [1, 2, 3]       # list
iex> {1, 2, 3}       # tuple
iex> %{key: "value"} # map

Basic Types

iex> x = 1
1
iex> 1 = x
1
iex> [a, b, c] = [1, 2, 3]
[1, 2, 3]
iex> a
1
iex> [head|tail] = [1,2,3]
[1, 2, 3]
iex> head
1
iex> tail
[2, 3]

Pattern Matching

iex> scores = %{ "users" => [{:alice, 500},
                             {:bob, 250},
                             {:carol, 100}] }
...
iex> %{"users" => [{first, _score}|_]} = scores
...
iex> first
:alice

Pattern Matching

iex> add = fn (a, b) -> a + b end
#Function<12.52032458/2 in :erl_eval.expr/5>
iex> add.(3, 5)
8
iex> add = &(&1+&2)
#&:erlang.+/2
iex> add.(3, 5)
8
iex> abs = fn (a) when a < 0 -> -a
              (a) -> a
           end
iex> abs.(-3)
3
iex> abs.(3)
3

Functions

iex> cond do
...>   2 + 2 == 5 ->
...>     "This will not be true"
...>   2 * 2 == 3 ->
...>     "Nor this"
...>   1 + 1 == 2 ->
...>     "But this will"
...> end
"But this will"
iex> if nil do
...>   "This won't be seen"
...> else
...>   "This will"
...> end
"This will"

Conditionals

case File.write("/path/to/file", content) do
  :ok -> :ok
  {:error, :enospc} ->
    IO.puts("Out of space.")
    {:error, :enospc}
  {:error, reason} ->
    IO.puts("""
    Didn't write to file because: #{inspect reason}.
    """)
    {:error, reason}
end

Conditionals

Hard Mode

iex> defmodule Test do
       def test(0) do
         IO.puts "Blastoff"
       end
       def test(n) do
         IO.puts "#{n}"
       end
     end
...
iex> Test.test(3)
3
2
1
Blastoff!
:ok

Modules

iex> defmodule Factorial do
       def fac(1) do
         1
       end 
       def fac(n) when n > 1 do
         n * fac(n - 1)
       end
     end
...
iex> Factorial.fac(5)
120

Modules

Language Basics

Functional

  • Code lives as functions in modules
  • Lambda functions also exist
  • All data is immutable
  • Emphasis on data transformation over collections and streams
iex> Enum.each([1,2,3], fn i -> IO.puts "Test #{i}" end)
Test 1
Test 2
Test 3
:ok
iex> Enum.filter([1,2,3], &Integer.is_odd?/2)
[1, 3]
iex> Enum.map([1,2,3], fn i ->
       IO.puts "Test #{i*2}"
       i * 2
     end)
Test 2
Test 4
Test 6
[2, 4, 6]

Iterating

Boring thing you're always doing

iex> "Hello, world!" |> IO.puts
Hello, world!
:ok
iex> [1,2,3]
     |> Enum.map(&(&1*3))
     |> Enum.filter(&Integer.is_odd?/1)
# Expands to:
#   Enum.filter(
#     Enum.map([1,2,3], &(&1*3)),
#     &Integer.is_odd?/1
#   )
[3, 9]

Pipe Operator

Amazing unix-like thing

[1,2,3,4,5]
|> Enum.filter(&Integer.is_odd?(&1))
|> case do
  [1,3,5] -> :correct
  _ -> :incorrect
end
|> IO.inspect
# Will print: :correct

Pipe Operator

Amazing unix-like thing

Language Basics

Concurrent + Parallel

  • Code runs in isolated processes (like OS processes)
  • Processes are scheduled by the VM, 1 scheduler per core
  • Processes have internal GC (no stop-the-world)
  • Processes are lightweight, 2KB or so of memory

Language Basics

Concurrent + Parallel

  • Processes communicate by sending messages (async)
  • A standard library called OTP provides building blocks for making applications

Language Basics

Distributed

  • Erlang VM (BEAM) can be connect to other instances over TCP or SSL
  • You can message a process ID to another VM and send messages
  • There are a few apps for making distributed applications

Language Basics

Fault-Tolerant

  • Erlang/Elixir libraries are called "applications"
  • If they need to store state, they start processes under a "supervisor"
  • When processes fail they can optionally be restarted, or reports can be filed for later inspection

Language Basics

Fault-Tolerant

  • "Let it crash", someone will restart
  • Works with computers
  • If you crash too much/too fast, the supervisor crashes
  • Putting too much defensive code is a bad "code smell"
  • Code assertively to crash early

What's it good for?

Basic Microservices

  • A process is practically a nanoservice
  • Applications form a backbone for microservices
  • "Releases" form a way of packaging up groups of applications as a single distributable

What's it good for?

The Web

  • Phoenix Framework is a first-class web framework
  • Offers familiar vocabulary to Rails
  • A separate library, ecto, provides DB interaction and is heavily inspired by MS's LINQ
  • Development is very quick and easy
  • Community is very active

What's in the Tooling

  • iex is a full Elixir shell, you can remote into nodes and restart the shell without restarting the VM
  • mix is a task runner and hosts the compiler and toolset
  • hex is a package repository for everything http://hex.pm/
  • elixir will run a plain elixir file

Tools

  • dialyzer will type-check your code
  • observer will let you look at a running system live
  • credo will give you opinions on your code and let you come up with style documents to enforce code style
  • ex_unit unit testing framework, extremely parallel

What's it good for?

Embedded Platforms

  • Nerves Project provides great development environment for embedded hardware
  • Needs about 32MB RAM, 200MHz, 16MB storage
  • Phoenix on RPi runs hundreds of requests per second baseline

What's it good for?

Embedded Platforms

  • You run a build and get a firmware file that's a few tens of MB
  • Mix will prompt you to burn on an SD card
  • A mix of read-only filesystems with writeable filesystems for configuration and logging prevent SD card and flash corruption

What it's not good for

  • Math: All integers are Bignums after Ericsson did a study on how much overflow bugs cost per year, so math is slow
  • Systems programming: You're not going to write an OS in this or a browser

Questions?

Let's start up a demo VM

ElixirTalk-0.0.1

By asonge

ElixirTalk-0.0.1

  • 361