Pro Yearly is on sale from $80 to $50! »

Elixir - introduction

Elixir - introduction

347a1b64f3a6e38981bc99b53919e2b1?s=128

karol.galanciak

November 18, 2015
Tweet

Transcript

  1. Elixir - Introduction

  2. Karol Galanciak • Full-stack developer at • Twitter: @Azdaroth •

    blog: karolgalanciak.com, blog.ragnarson.com
  3. Programming should be about transforming data

  4. Programming should be about transforming data OOP:

  5. Programming should be about transforming data OOP: • classes

  6. Programming should be about transforming data OOP: • classes •

    objects
  7. Programming should be about transforming data OOP: • classes •

    objects • state
  8. Programming should be about transforming data OOP: • classes •

    objects • state • modelling real world with hierarchies
  9. Programming should be about transforming data Elixir:

  10. Programming should be about transforming data Elixir: getting things done

  11. Why Elixir?

  12. Why Elixir? • Functional

  13. Why Elixir? • Functional: • immutability

  14. Why Elixir? • Functional: • immutability • pattern matching

  15. Why Elixir? • Functional: • pattern matching • immutability •

    side-effects free
  16. Why Elixir? • Functional • Erlang VM

  17. Why Elixir? • Functional • Erlang VM • Concurrency

  18. Why Elixir? • Functional • Erlang VM • Concurrency •

    Syntax
  19. Why Elixir? • Functional • Erlang VM • Concurrency •

    Syntax • Erlang compatible
  20. Match operator • a = 1

  21. Match operator • a = 1=> 1

  22. Match operator • a = 1 => 1 • 1

    = a
  23. Match operator • a = 1 => 1 • 1

    = a => 1
  24. Match operator • a = 1 => 1 • 1

    = a => 1 • 2 = a
  25. Match operator • a = 1 => 1 • 1

    = a => 1 • 2 = a => (MatchError) no match of right hand side value: 1
  26. Match operator • a = 1 => 1 • 1

    = a => 1 • 2 = a => (MatchError) no match of right hand side value: 1 • list = [1, 2, 3]
  27. Match operator • a = 1 => 1 • 1

    = a => 1 • 2 = a => (MatchError) no match of right hand side value: 1 • list = [1, 2, 3] • [a, b, c] = list
  28. Match operator • a = 1 => 1 • 1

    = a => 1 • 2 = a => (MatchError) no match of right hand side value: 1 • list = [1, 2, 3] • [a, b, c] = list • [1, b, 3] = list
  29. Match operator • a = 1 => 1 • 1

    = a => 1 • 2 = a => (MatchError) no match of right hand side value: 1 • list = [1, 2, 3] • [a, b, c] = list • [1, b, 3] = list • [2, 2, 3] = list
  30. Match operator • a = 1 => 1 • 1

    = a => 1 • 2 = a => (MatchError) no match of right hand side value: 1 • list = [1, 2, 3] • [a, b, c] = list • [1, b, 3] = list • [2, 2, 3] = list • [d, _, _] = list
  31. Match operator • a = 1 => 1 • 1

    = a => 1 • 2 = a => (MatchError) no match of right hand side value: 1 • list = [1, 2, 3] • [a, b, c] = list • [1, b, 3] = list • [2, 2, 3] = list • [d, _, _] = list • { status, _ } = { :ok, ”content” }
  32. Types

  33. Types • Value Types:

  34. Types • Value Types: • Integers

  35. Types • Value Types: • Integers • Floats

  36. Types • Value Types: • Integers • Floats • Atoms

    (:like_ruby_symbol)
  37. Types • Value Types: • Integers • Floats • Atoms

    (:like_ruby_symbol) • Ranges (1..100)
  38. Types • Value Types: • Integers • Floats • Atoms

    (:like_ruby_symbol) • Ranges (1..100) • Regular expressions (%r{regexp})
  39. Tpes • System types:

  40. Types • System types: • PIDs

  41. Types • System types: • PIDs • Ports

  42. Types • System types: • PIDs • Ports • References

  43. Types • Collection types:

  44. Types • Collection types: • Tuples

  45. Types • Collection types: • Tuples • => {:ok, ”content”}

  46. Types • Collection types: • Tuples • => {:ok, ”content”}

    • => {:error, ”error message”}
  47. Types • Collection types: • Tuples • => {:ok, ”content”}

    • => {:error, ”error message”} • Lists
  48. Types • Collection types: • Tuples • => {:ok, ”content”}

    • => {:error, ”error message”} • Lists • => [1, 2, 3]
  49. Types • Collection types: • Tuples • => {:ok, ”content”}

    • => {:error, ”error message”} • Lists • => [1, 2, 3] • => [1, 2, 3] ++ [4]
  50. Types • Collection types: • Tuples • => {:ok, ”content”}

    • => {:error, ”error message”} • Lists • => [1, 2, 3] • => [1, 2, 3] ++ [4] • => [1, 2, 3] -- [1]
  51. Types • Collection types: • Tuples • => {:ok, ”content”}

    • => {:error, ”error message”} • Lists • => [1, 2, 3] • => [1, 2, 3] ++ [4] • => [1, 2, 3] -- [1] • => 1 in [1, 2, 3]
  52. Types • Collection types: • Keyword Lists

  53. Types • Collection types: • Keyword Lists • => [name:

    ”Elixir”, status: ”awesome”]
  54. Types • Collection types: • Keyword Lists • => [name:

    ”Elixir”, status: ”awesome”] • => [name: ”Elixir”, status: ”awesome”][:name]
  55. Types • Collection types: • Keyword Lists • => [name:

    ”Elixir”, status: ”awesome”] • => [name: ”Elixir”, status: ”awesome”][:name] • Maps
  56. Types • Collection types: • Keyword Lists • => [name:

    ”Elixir”, status: ”awesome”] • => [name: ”Elixir”, status: ”awesome”][:name] • Maps • %{”ruby” => ”oop”, :elixir => ”functional”}
  57. Types • Collection types: • Keyword Lists • => [name:

    ”Elixir”, status: ”awesome”] • => [name: ”Elixir”, status: ”awesome”][:name] • Maps • %{”ruby” => ”oop”, :elixir => ”functional”} • %{”ruby” => ”oop”, :elixir => ”functional”}[:elixir]
  58. Functions

  59. Functions • add_one = fn n -> n + 1

    end
  60. Functions • add_one = fn n -> n + 1

    end • add_one.(1) => 2
  61. Functions • add_one = fn n -> n + 1

    end • add_one.(1) => 2 • square = &(&1 * &1)
  62. Functions • add_one = fn n -> n + 1

    end • add_one.(1) => 2 • square = &(&1 * &1) • => square.(3) => 9
  63. Functions • add_one = fn n -> n + 1

    end • add_one.(1) => 2 • square = &(&1 * &1) • => square.(3) => 9 • len = &Enum.count/1
  64. Functions • add_one = fn n -> n + 1

    end • add_one.(1) => 2 • square = &(&1 * &1) • => square.(3) => 9 • len = &Enum.count/1 • len.([1, 2, 3]) => 3
  65. Organizing code

  66. Organizing code defmodule SomeName do end

  67. Organizing code defmodule SomeName do def hello_world do IO.puts ”hello

    world” end end
  68. Organizing code defmodule SomeName do def hello_world do IO.puts ”hello

    world” end end SomeName.hello_world => ”hello world”
  69. Functions and Pattern Matching

  70. Functions and Pattern Matching defmodule MySum do end

  71. Functions and Pattern Matching defmodule MySum do def sum(array), do:

    _sum(0, array) end
  72. Functions and Pattern Matching defmodule MySum do def sum(array), do:

    _sum(0, array) defp _sum(total, []), do: total end
  73. Functions and Pattern Matching defmodule MySum do def sum(array), do:

    _sum(0, array) defp _sum(total, []), do: total defp _sum(total, [head | tail]), do: _sum(total + head, tail) end
  74. Functions and Pattern Matching defmodule MySum do def sum([head |

    tail]), do: _sum(head, tail) defp _sum(total, []), do: total defp _sum(total, [head | tail]), do: _sum(total + head, tail) end MySum.sum([1, 2, 3]) => 6
  75. Guard Clauses

  76. Guard Clauses defmodule NumberType do def print_type(num) when num <

    0 do IO.puts "#{num} - I’m negative!" end def print_type(num) when num == 0 do IO.puts "I’m 0!" end def print_type(num) when num > 0 do IO.puts "#{num} - I’m positive!" end end
  77. Guard Clauses defmodule NumberType do def print_type(num) when num <

    0 do IO.puts "#{num} - I’m negative!" end def print_type(num) when num == 0 do IO.puts "I’m 0!" end def print_type(num) when num > 0 do IO.puts "#{num} - I’m positive!" end end • NumberType.print_type(1) => 1 - I’m positive! • NumberType.print_type(0) => I’m 0! • NumberType.print_type(-1) => -1 - I’m negative!
  78. Pipe operator - |> ps awux | grep spring |

    awk '{print $2}' | xargs kill
  79. Pipe operator - |> [1, 2, 3] |> Enum.map(&(&1 *

    &1)) |> Enum.map(&to_string/1) |> Enum.map(&(&1 <> "0")) |> Enum.join(" - ") => "10 - 40 - 90"
  80. List comprehensions

  81. List comprehensions for x <- [1, 2, 3], y <-

    [10, 20, 30], x * y > 20, do: x + y => [31, 22, 32, 13, 23, 33]
  82. Cond, if, case

  83. Cond, if, case if 1 == 1 do ”I’m truthy”

    else ”I’m falsey” end
  84. Cond, if, case if 1 == 1 do ”I’m truthy”

    else ”I’m falsey” end unless 1 == 1, do: ”error”, else: ”ok”
  85. Cond, if, case cond do rem(number, 3) == 0 and

    rem(number, 5) == 0 -> "FizzBuzz" rem(number, 3) == 0 -> "Fizz" rem(number, 5) == 0 -> "Buzz" true -> number end
  86. Cond, if, case case File.open(”some_file.exs”) do { :ok, file }

    => IO.puts ”success” { :error, reason } => IO.puts ”error: #{reason}” end
  87. Structs

  88. Structs defmodule User do defstruct fullname: "", email: "" end

  89. Structs defmodule User do defstruct fullname: "", email: "" end

    user = %User{fullname: ”name”}
  90. Structs defmodule User do defstruct fullname: "", email: "" end

    user = %User{fullname: ”name”} user.fullname = > ”name”
  91. Structs defmodule User do defstruct fullname: "", email: "" def

    has_email?(user) do String.length(user.email) > 0 end end
  92. Macros

  93. Macros defmodule Test do require Plus Plus.add_n(3) Plus.add_n(4) end Test.add_3(4)

    => 7 Test.add_4(5) => 9
  94. Macros defmodule Plus do defmacro add_n(number) do name = String.to_atom("add_#{number}")

    quote do def unquote(name)(other_number) do other_number + unquote(number) end end end end
  95. Concurrency

  96. Concurrency defmodule Spawnee do def hi do receive do {

    sender, message } -> send sender, { :ok, "Hi #{message}!"} end end end
  97. Concurrency defmodule Spawnee do def hi do receive do {

    sender, message } -> send sender, { :ok, "Hi #{message}!"} end end end pid = spawn(Spawnee, :hi, []) send pid, { self, "Elixir" }
  98. Concurrency defmodule Spawnee do def hi do receive do {

    sender, message } -> send sender, { :ok, "Hi #{message}!"} end end end pid = spawn(Spawnee, :hi, []) send pid, { self, "Elixir" } receive do { :ok, message } -> IO.puts message end
  99. Concurrency defmodule Spawnee do def hi do receive do {

    sender, message } -> send sender, { :ok, "Hi #{message}!"} end end end pid = spawn(Spawnee, :hi, []) send pid, { self, "Elixir" } receive do { :ok, message } -> IO.puts message end => Hi Elixir! :ok
  100. Encapsulating state by processes

  101. Encapsulating state by processes defmodule Counter do def start do

    do_count(0) end defp do_count(current_number) do receive do { :increment, listener } -> send listener, current_number + 1 do_count(current_number + 1) end end end
  102. Encapsulating state by processes defmodule Counter do def start do

    do_count(0) end defp do_count(current_number) do receive do { :increment, listener } -> send listener, current_number + 1 do_count(current_number + 1) end end end counter_pid = spawn(Counter, :start, []) send(counter_pid, { :increment, self }) receive do count -> count end => 1
  103. Encapsulating state by processes defmodule Counter do def start do

    do_count(0) end defp do_count(current_number) do receive do { :increment, listener } -> send listener, current_number + 1 do_count(current_number + 1) end end end counter_pid = spawn(Counter, :start, []) send(counter_pid, { :increment, self }) receive do count -> count end => 1 send(counter_pid, { :increment, self }) receive do count -> count end => 2
  104. Elixir FTW!