Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Elixir: A Talk For College Students

Elixir: A Talk For College Students

Slides for a talk I gave on CodeWeek 2015 (http://cesium.di.uminho.pt/codeweek15)

The talk was divided into 2 parts: the first was a small introduction to the language, with lots of small examples from the official Getting Started guide. The second part was a small in-depth guide to OTP and the actor model.

All code examples are available on https://github.com/frmendes/elixir-intro

I lost the references I had saved for the pictures. Contact me if I used your photos and you want to be referenced.

Fernando Mendes

October 14, 2015
Tweet

More Decks by Fernando Mendes

Other Decks in Programming

Transcript

  1. ELIXIR
    a talk for college students
    CodeWeek 15
    Informatics Dept. , UMinho

    View Slide

  2. STORYTIME

    View Slide

  3. 23/09/2011


    View Slide

  4. 23/09/2011

    ONE MILLION TCP CONNECTIONS

    View Slide

  5. 23/09/2011

    ONE MILLION TCP CONNECTIONS
    ON A SINGLE NODE

    View Slide

  6. 23/09/2011

    ONE MILLION TCP CONNECTIONS
    ON A SINGLE NODE
    WITH RESOURCES TO SPARE

    View Slide

  7. 23/09/2011

    ONE MILLION TCP CONNECTIONS
    ON A SINGLE NODE
    WITH RESOURCES TO SPARE

    View Slide

  8. • FUNCTIONAL
    • FAULT TOLERANT
    • DISTRIBUTED & SCALABLE
    • PARALLEL
    • HOT CODE SWAPPING

    View Slide

  9. • LIGHTWEIGHT PROCESSES
    • ACTOR MODEL
    • TRIED AND TESTED VM
    • GARBAGE COLLECTION
    • NETWORK PROTOCOLS

    View Slide

  10. View Slide

  11. ERLANG
    iS
    AWESOME

    View Slide

  12. ERLANG
    iS
    AWESOME
    … but why Elixir, then?

    View Slide

  13. github: @frmendes
    everywhere else: @fribmendes
    my awesome sister who
    doesn’t code but it’s all good
    ‘cause she doesn’t like Java

    View Slide

  14. View Slide

  15. View Slide

  16. love me, please
    lol, not my cat

    View Slide

  17. ELIXIR
    everything erlang has to offer

    View Slide

  18. beautiful syntax
    ELIXIR

    View Slide

  19. powerful libraries
    ELIXIR

    View Slide

  20. metaprogramming \m/
    ELIXIR

    View Slide

  21. awesome DSLs
    ELIXIR

    View Slide

  22. mix ecosystem
    ELIXIR

    View Slide

  23. ELIXIR
    AS A LANGUAGE

    View Slide

  24. 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
    ELIXIR

    View Slide

  25. LISTS

    View Slide

  26. iex> [1, 2, true, 3]

    [1, 2, true, 3]
    iex> tuple = {:ok, "hello"}
    {:ok, “hello”}
    ELIXIR
    linked list
    tuple - contiguous memory

    View Slide

  27. iex> tuple = {:ok, "hello"}
    {:ok, “hello”}
    iex> put_elem(tuple, 1, "world")
    {:ok, “world”}
    iex> tuple
    {:ok, “hello”}
    ELIXIR

    View Slide

  28. iex> tuple = {:ok, "hello"}
    {:ok, “hello”}
    iex> put_elem(tuple, 1, "world")
    {:ok, “world”}
    iex> tuple
    {:ok, “hello”}
    ELIXIR
    immutability
    aka “lolno.”

    View Slide

  29. PATTERN MATCHING

    View Slide

  30. iex> x = 1
    1
    iex> x
    1
    iex> 1 = x
    1
    ELIXIR

    View Slide

  31. iex> x = 1
    1
    iex> x
    1
    iex> 1 = x
    1
    ELIXIR
    x = 1?
    what is 1?
    1 is 1
    x is 1

    View Slide

  32. iex> x = 1
    1
    iex> x
    1
    iex> 1 = x
    1
    ELIXIR
    I know what’s 1! it’s x!

    View Slide

  33. iex> x = 1
    1
    iex> 2 = x
    ** (MatchError) no match of right hand side value: 1
    iex> 1 = y
    ** (RuntimeError) undefined function: y/0
    ELIXIR
    What is 1?

    View Slide

  34. iex> x = 1
    1
    iex> 2 = x
    ** (MatchError) no match of right hand side value: 1
    iex> 1 = y
    ** (RuntimeError) undefined function: y/0
    ELIXIR
    I don’t know y so y can’t be 1

    View Slide

  35. iex> [head | tail] = [1, 2, 3]
    [1, 2, 3]
    iex> head
    1
    iex> tail
    [2, 3]
    ELIXIR

    View Slide

  36. iex> x = 1
    1
    iex> ^x = 2
    ** (MatchError) no match of right hand side value: 2
    ELIXIR

    View Slide

  37. int x = 1;
    if (x == 1)
    y = 2;
    JAVA

    View Slide

  38. int x = 1;
    if (x == 1)
    y = 2;
    JAVA
    x = 1
    y = 2 if x = 1
    RUBY

    View Slide

  39. int x = 1;
    if (x == 1)
    y = 2;
    JAVA
    x = 1
    y = f x
    where f 1 = 2
    HASKELL
    x = 1
    y = 2 if x = 1
    RUBY

    View Slide

  40. int x = 1;
    if (x == 1)
    y = 2;
    JAVA
    x = 1
    y = f x
    where f 1 = 2
    HASKELL
    x = 1
    y = 2 if x = 1
    RUBY
    x = 1
    {y, ^x} = {2, 1}
    ELIXIR

    View Slide

  41. iex> 'hello' == "hello"
    false
    iex> [104, 101, 108, 108, 111]
    'hello'
    ELIXIR

    View Slide

  42. iex> 'hello' == "hello"
    false
    iex> [104, 101, 108, 108, 111]
    'hello'
    ELIXIR
    wait, what?

    View Slide

  43. STRINGS

    View Slide

  44. STRINGS
    UTF-8

    View Slide

  45. STRINGS
    UTF-8

    View Slide

  46. “”.length
    ?

    View Slide

  47. “”.size
    ?

    View Slide

  48. “”.size
    4 bytes each emoji

    View Slide

  49. “baffle”.length
    ?

    View Slide

  50. “baffle”.size
    ?

    View Slide

  51. “baffle”.size
    length 4
    size 6

    View Slide

  52. string types are hard

    View Slide

  53. string types usually suck

    View Slide

  54. string types usually suck
    usually

    View Slide

  55. “”.length();
    > 8
    “baffle”.length();
    > 4
    JAVA
    ffl is a single unicode character

    View Slide

  56. new StringBuilder(“baffle”).reverse();
    > “efflab”
    “baffle”.toUpperCase();
    > “BAFFLE”
    JAVA

    View Slide

  57. “”.length
    > 4
    “baffle”.length
    > 4
    RUBY

    View Slide

  58. “baffle”.reverse
    > “efflab”
    “baffle”.upcase
    > “BAfflE”
    RUBY

    View Slide

  59. def
    puts “it works!”
    end

    > “it works!”
    RUBY
    UTF-8 file encoding
    means we get to write
    awesome,
    readable code!

    View Slide

  60. iex> byte_size “”
    16
    iex> String.length “”
    4
    ELIXIR

    View Slide

  61. iex> byte_size “baffle”
    6
    iex> String.length “baffle”
    4
    ELIXIR

    View Slide

  62. iex> String.codepoints “”
    [“”, “”, “”, “”]
    iex> String.codepoints “baffle”
    [“b”, “a”, “ffl”, “e”]
    iex> to_char_list “baffle”
    [98, 97, 64260, 101]
    ELIXIR

    View Slide

  63. iex> String.reverse “baffle”
    “efflab”
    iex> String.upcase “baffle”
    “BAFFLE”
    ELIXIR

    View Slide

  64. iex> "he" <> "llo"
    “hello"
    iex> "he" <> rest = "hello"
    “hello"
    iex> rest
    "llo"
    ELIXIR
    Concatenation operator for
    pattern matching

    View Slide

  65. BINARIES

    View Slide

  66. iex> <<0, 1, 2, 3>>
    <<0, 1, 2, 3>>
    iex> byte_size <<0, 1, 2, 3>>
    4
    ELIXIR
    “basically” a byte array

    View Slide

  67. iex> <<256>>
    <<0>>
    iex> <<256 :: size(16)>>
    <<1, 0>>
    ELIXIR
    truncation
    “yo, use 2 bytes!”

    View Slide

  68. iex> <<256 :: utf8>>
    "Ā"
    ELIXIR
    treat as codepoint

    View Slide

  69. iex> <<1 :: size(1)>>
    <<1::size(1)>>
    iex> <<2 :: size(1)>>
    <<0::size(1)>>
    ELIXIR
    truncation
    use a single bit

    View Slide

  70. iex> is_binary(<< 1 :: size(1)>>)
    false
    iex> is_bitstring(<< 1 :: size(1)>>)
    true
    ELIXIR

    View Slide

  71. iex> bit_size(<< 1 :: size(1)>>)
    1
    iex> byte_size(<< 1 :: size(1)>>)
    1
    ELIXIR
    Erlang VM still allocates 1 byte

    View Slide

  72. iex> byte_size(<< 1 :: size(8)>>)
    1
    iex> byte_size(<< 1 :: size(9)>>)
    2
    ELIXIR
    byte allocation

    View Slide

  73. KEYWORD LISTS

    View Slide

  74. iex> list = [{:a, 1}, {:b, 2}]
    [a: 1, b: 2]
    iex> list == [a: 1, b: 2]
    true
    iex> list[:a]
    1
    ELIXIR
    special keyword list syntax

    View Slide

  75. iex> new_list = [a: 0] ++ list
    [a: 0, a: 1, b: 2]
    iex> new_list[:a]
    0
    ELIXIR
    Allows
    repeated keys

    View Slide

  76. iex> new_list = [a: 0] ++ list
    [a: 0, a: 1, b: 2]
    iex> new_list[:a]
    0
    ELIXIR
    first value of the lookup

    View Slide

  77. iex> if(false, [do: :this, else: :that])
    :that
    ELIXIR

    View Slide

  78. query = from w in Weather,
    where: w.prcp > 0,
    where: w.temp < 20,
    select: w
    ELIXIR

    View Slide

  79. MAPS

    View Slide

  80. Map map = new HashMap<>();
    map.put(“a”, 1);
    map.put(“b”, 2);
    JAVA

    View Slide

  81. Map map = new HashMap<>();
    map.put(“a”, 1);
    map.put(“b”, 2);
    JAVA
    Short version is long

    View Slide

  82. Map map = new HashMap<>();
    map.put(“a”, 1);
    map.put(“b”, 2);
    JAVA
    Auto-boxing

    View Slide

  83. map = {a: 1, b: 2}
    other_map = {a: 1, 2 => :b}
    RUBY

    View Slide

  84. map = %{a: 1, b: 2}
    other_map = %{a: 1, 2 => :b}
    ELIXIR

    View Slide

  85. iex> other_map[2]
    :b
    iex> %{a: a} = other_map
    %{a: 1, 2 => :b}
    iex> a
    1
    ELIXIR
    Elegant pattern matching

    View Slide

  86. iex> %{b: b} = other_map
    ** (MatchError) no match of right hand side value:
    %{2 => :b, :a => 1}
    iex> other_map[:b]
    nil
    ELIXIR
    Elegant pattern matching failing
    No error

    View Slide

  87. LOGICAL OPERATORS

    View Slide

  88. 1> true and false.
    false
    2> false or true.
    true
    3> not (true and true)
    false
    ERLANG

    View Slide

  89. 1> true and false.
    false
    2> false or true.
    true
    3> not (true and true)
    false
    ERLANG
    Always evaluate on each side

    View Slide

  90. 1> true andalso false.
    false
    2> false orelse true.
    true
    ERLANG
    Short-circuit operators

    View Slide

  91. iex> true and true
    true
    iex> false or is_atom(:example)
    true
    ELIXIR
    Short-circuit operators

    View Slide

  92. iex> false and raise("This error will
    never be raised")
    false
    iex> true or raise("This error will
    never be raised")
    true
    ELIXIR

    View Slide

  93. CONTROL FLOW

    View Slide

  94. int x = 1;
    switch(x) {
    case 1:
    System.out.println(“Will match”);
    break;
    default:
    System.out.println(“Doesn’t match”);
    }
    JAVA

    View Slide

  95. int x = 1;
    switch(x) {
    case 1:
    System.out.println(“Will match”);
    break;
    default:
    System.out.println(“Doesn’t match”);
    }
    JAVA
    No extra conditions

    View Slide

  96. iex> case {1, 2, 3} do
    ...> {4, 5, 6} ->
    ...> "This clause won't match"
    ...> {1, x, 3} ->
    ...> "This clause will match and bind x to 2"
    ...> _ ->
    ...> "This clause would match any value"
    ...> end
    "This clause will match and bind x to 2"
    ELIXIR

    View Slide

  97. iex> case {1, 2, 3} do
    ...> {4, 5, 6} ->
    ...> "This clause won't match"
    ...> {1, x, 3} ->
    ...> "This clause will match and bind x to 2"
    ...> _ ->
    ...> "This clause would match any value"
    ...> end
    "This clause will match and bind x to 2"
    ELIXIR
    binds x to 2

    View Slide

  98. iex> case {1, 2, 3} do
    ...> {4, 5, 6} ->
    ...> "This clause won't match"
    ...> {1, x, 3} ->
    ...> "This clause will match and bind x to 2"
    ...> _ ->
    ...> "This clause would match any value"
    ...> end
    "This clause will match and bind x to 2"
    ELIXIR
    but x is only valid in this scope

    View Slide

  99. iex> x = 1
    1
    iex> case 10 do
    ...> ^x -> "Won't match"
    ...> _ -> "Will match"
    ...> end
    "Will match"
    ELIXIR
    Pin operator allows comparison

    View Slide

  100. iex> case {1, 2, 3} do
    ...> {1, x, 3} when x > 0 ->
    ...> "Will match"
    ...> _ ->
    ...> “Won’t match"
    ...> end
    "Will match"
    ELIXIR
    Scoped assignment allows guards

    View Slide

  101. iex> if true do
    ...> "This works!"
    ...> end
    “This works!”
    ELIXIR

    View Slide

  102. iex> unless false do
    ...> "This works!"
    ...> end
    “This works!”
    ELIXIR

    View Slide

  103. iex> if nil do
    ...> "This won't be seen"
    ...> else
    ...> "This will"
    ...> end
    "This will"
    ELIXIR

    View Slide

  104. iex> if nil do
    ...> "This won't be seen”
    ...> else if
    ...> "This is an error"
    ...> else
    ...> "This will"
    ...> end
    "This will"
    ELIXIR

    View Slide

  105. iex> if nil do
    ...> "This won't be seen”
    ...> else if
    ...> "This is an error"
    ...> else
    ...> "This will"
    ...> end
    "This will"
    ELIXIR

    View Slide

  106. iex> if(false, [do: :this, else: :that])
    :that
    ELIXIR

    View Slide

  107. iex> cond do
    ...> 2 + 2 == 5 ->
    ...> "This is never true"
    ...> 2 * 2 == 3 ->
    ...> "Nor this"
    ...> true ->
    ...> "This is always true (equivalent
    to else)"
    ...> end
    ELIXIR

    View Slide

  108. FUNCTIONS

    View Slide

  109. def add(x, y) do
    x + y
    end
    ELIXIR
    Needs to be inside a module

    View Slide

  110. def add(x, 0) do
    x
    end
    ELIXIR
    Arguments can do pattern matching

    View Slide

  111. def add(x, y) when x == 0 do
    y
    end
    ELIXIR
    And we can use guards

    View Slide

  112. add2 = fn
    x, y when x == 0 -> y
    x, 0 -> x
    x, y -> x + y
    end
    ELIXIR
    Anonymous function

    View Slide

  113. iex> Arithmetic.add(1, 3)
    4
    iex> add2.(-1, 0)
    -1
    ELIXIR
    Module name

    View Slide

  114. arity identifies functions

    View Slide

  115. def add(x, y) do
    x + y
    end
    def add(x) do
    x + 1
    end
    ELIXIR
    add/1
    add/2

    View Slide

  116. add2 = fn
    x, y -> x + y
    x -> 0
    end
    ** (SyntaxError) cannot mix clauses with different
    arities in function definition
    ELIXIR

    View Slide

  117. anonymous functions are closures

    View Slide

  118. iex> x = 1
    iex> add_x = fn y -> x + y end
    iex> add_x.(2)
    3
    ELIXIR

    View Slide

  119. x = 1
    def add_x(y) do
    x + y
    end
    ELIXIR

    View Slide

  120. x = 1
    def add_x(y) do
    x + y
    end
    ELIXIR
    compile error

    View Slide

  121. x = 1
    def add_x(y) do
    x + y
    end
    ELIXIR
    each function definition has a blank scope

    View Slide

  122. anonymous functions are callable

    View Slide

  123. iex> add_one = fn x -> x + 1 end
    iex> Enum.map([1, 2, 3, 4], add_one)
    [2, 3, 4, 5]
    ELIXIR

    View Slide

  124. iex> defmodule Arith do
    ...> def add_two(x), do: x + 2
    ...> end
    iex> Enum.map([1, 2, 3, 4],
    &Arith.add_two/1)
    [2, 3, 4, 5]
    ELIXIR
    capture syntax

    View Slide

  125. ENUMS & STREAMS

    View Slide

  126. iex> add_one = fn x -> x + 1 end
    iex> Enum.map([1, 2, 3, 4], add_one)
    [2, 3, 4, 5]
    ELIXIR
    Enum module

    View Slide

  127. iex> 0..99 |> Enum.map(&(&1 + 1))
    |> Enum.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR

    View Slide

  128. iex> 0..99 |> Enum.map(&(&1 + 1))
    |> Enum.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    pipe operator - similar to unix pipe

    View Slide

  129. iex> 0..99 |> Enum.map(&(&1 + 1))
    |> Enum.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    capturing a function

    View Slide

  130. iex> 0..99 |> Enum.map(&(&1 + 1))
    |> Enum.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    first argument passed to the function

    View Slide

  131. iex> 0..99 |> Enum.map(&(&1 + 1))
    |> Enum.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    capture module function

    View Slide

  132. iex> 0..99 |> Enum.map(&(&1 + 1))
    |> Enum.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    Enum is eager: every operation generates an intermediate list

    View Slide

  133. iex> 0..99 |> Stream.map(&(&1 + 1))
    |> Stream.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    Stream is lazy: every operation returns another stream

    View Slide

  134. iex> 0..99 |> Stream.map(&(&1 + 1))
    |> Stream.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    Enum is used to make the calculation

    View Slide

  135. iex> 0..99 |> Stream.map(&(&1 + 1))
    |> Stream.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    Enum is used to make the calculation

    View Slide

  136. iex> 0..99 |> Stream.map(&(&1 + 1))
    |> Stream.filter(&Integer.is_odd/1)
    |> Enum.sum
    ELIXIR
    Stream only carries a set of operations
    to make somewhere in the future

    View Slide

  137. iex> stream = Stream.cycle([1, 2, 3])
    iex> Enum.take(stream, 10)
    [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
    ELIXIR
    infinite set

    View Slide

  138. ELIXIR
    ACTOR MODEL & OTP

    View Slide

  139. PROCESSES

    View Slide

  140. ELIXIR PROCESSES

    OS PROCESSES

    View Slide

  141. “An actor is an entity that receives messages and,
    according to those messages, can
    send more messages,
    create a finite number of actors and
    choose behaviour for processing the next message”
    - Carl Hewitt, 1973

    View Slide

  142. Actors are processes.
    Processes act upon messages.
    Each process has a mailbox.
    Messages are asynchronous and there are no guarantees
    regarding delivery.
    Each process has its own state, which is not shared.

    View Slide

  143. parent = self
    spawn fn -> send(parent, {:hello, self}) end
    receive do
    {:hello, pid} -> IO.puts “Hello #{inspect pid}”
    end

    View Slide

  144. what if…
    no one is listening?

    View Slide

  145. Actors are processes.
    Processes act upon messages.
    Each process has a mailbox.
    Messages are asynchronous and there are no guarantees
    regarding delivery.
    Each process has its own state, which is not shared.
    Each process has a mailbox.

    View Slide

  146. what if…
    we received an unexpected message?

    View Slide

  147. FUNCTIONAL PARADIGM™
    everything
    is immutable

    View Slide

  148. immutable
    ≠ stateless
    FUNCTIONAL PARADIGM™

    View Slide

  149. OOP
    behaviour
    CLASS
    state
    INSTANCE

    View Slide

  150. FP
    behaviour
    MODULE
    state
    PROCESS

    View Slide

  151. A SAMPLE QUEUE

    View Slide

  152. defmodule Queue do
    use GenServer
    def new do
    GenServer.start_link(Queue, [], [])
    end
    end

    View Slide

  153. def handle_cast({:put, value}, state) do
    {:noreply, state ++ [value]}
    end
    Server callbacks

    View Slide

  154. def handle_call(:poll, _from, []) do
    {:reply, nil, []}
    end
    def handle_call(:poll, _from, state) do
    [head|tail] = state
    {:reply, head, tail}
    end Server callbacks

    View Slide

  155. iex> {:ok, q} = Queue.new
    iex> GenServer.cast(q, {:put, 1})
    iex> GenServer.call(q, :poll)
    1

    View Slide

  156. def put(queue, value) do
    GenServer.cast(queue, {:put, value})
    end
    def poll(queue) do
    GenServer.call(queue, :poll)
    end Client callbacks

    View Slide

  157. iex> {:ok, q} = Queue.new
    iex> Queue.put(q, 1)
    iex> Queue.poll(q)
    1

    View Slide

  158. TASK

    View Slide

  159. “Tasks are processes meant to execute one
    particular action throughout their life-cycle,
    often with little or no communication with other
    processes.”
    - Elixir Docs, 2015

    View Slide

  160. FAILURES

    View Slide

  161. “The greatest advantage actor-based systems
    give us is accepting programmers make
    mistakes all the time and not all scenarios are
    testable.”
    - Me, right now

    View Slide

  162. fail
    fast

    View Slide

  163. let
    crash
    it

    View Slide

  164. try do
    raise "oops"
    rescue
    e in RuntimeError -> e
    end

    View Slide

  165. try do
    raise "oops"
    rescue
    e in RuntimeError -> e
    end
    don’t care about failures

    View Slide

  166. try do
    raise "oops"
    rescue
    e in RuntimeError -> e
    end
    use Supervisors instead

    View Slide

  167. try do
    raise "oops"
    rescue
    e in RuntimeError -> e
    end
    keep your code clean

    View Slide

  168. try do
    raise "oops"
    rescue
    e in RuntimeError -> e
    end
    keep your flow clean

    View Slide

  169. A SAMPLE CHAT

    View Slide

  170. def listen(port) do
    {:ok, socket} = :gen_tcp.listen(port,
    [:list, packet: :line,
    active: false,
    reuseaddr: true])
    acceptor(socket)
    end
    Server Module

    View Slide

  171. defp acceptor(socket) do
    {:ok, client} = :gen_tcp.accept(socket)
    handle_client(client)
    acceptor(socket)
    end
    Server Module

    View Slide

  172. defp handle_client(client) do
    client |> read() |> write(client)
    handle_client(client)
    end
    Server Module

    View Slide

  173. defp read(socket) do
    # 2nd param is byte length
    # 0 means receive all available bytes
    {:ok, data} = :gen_tcp.recv(socket, 0)
    data
    end
    Server Module

    View Slide

  174. defp write(msg, socket) do
    :gen_tcp.send(socket, msg)
    end
    Server Module

    View Slide

  175. what if…
    we want to echo multiple clients?

    View Slide

  176. def start do
    import Supervisor.Spec
    children = [
    supervisor(Task.Supervisor, [[name: Server.TaskSupervisor]]),
    worker(Task, [Server, :listen, [3000]])
    ]
    opts = [strategy: :one_for_one, name: ServerSupervisor]
    Supervisor.start_link(children, opts)
    end
    Server Module

    View Slide

  177. defp acceptor(socket) do
    {:ok, client} = :gen_tcp.accept(socket)
    handle_client(client)
    acceptor(socket)
    end
    Old Server Module

    View Slide

  178. defp acceptor(socket) do
    {:ok, client} = :gen_tcp.accept(socket)
    {:ok, pid} = Task.Supervisor.start_child(
    Server.TaskSupervisor, fn -> handle_client(client) end)
    # transferring the socket control to the new child
    :ok = :gen_tcp.controlling_process(client, pid)
    acceptor(socket)
    end New Server Module

    View Slide

  179. ELIXIR
    a talk for college students
    @frmendes
    @fribmendes

    View Slide