karol.galanciak
November 18, 2015
160

# Elixir - introduction

## karol.galanciak

November 18, 2015

## Transcript

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

blog: karolgalanciak.com, blog.ragnarson.com

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

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

side-effects free

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

Syntax • Erlang compatible

= a

= 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” }

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})

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]

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]

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

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”

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

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"

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

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

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_ﬁle.exs”) do { :ok, ﬁle }

=> IO.puts ”success” { :error, reason } => IO.puts ”error: #{reason}” 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

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

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

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