karol.galanciak
November 18, 2015
140

# Elixir - introduction

## karol.galanciak

November 18, 2015

## Transcript

1. Elixir - Introduction

2. Karol Galanciak
• Full-stack developer at
• blog: karolgalanciak.com, blog.ragnarson.com

3. Programming should be

4. Programming should be
OOP:

5. Programming should be
OOP:
• classes

6. Programming should be
OOP:
• classes
• objects

7. Programming should be
OOP:
• classes
• objects
• state

8. Programming should be
OOP:
• classes
• objects
• state
• modelling real world with hierarchies

9. Programming should be
Elixir:

10. Programming should be
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

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

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

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

64. Functions
• add_one = fn n -> n + 1 end
• 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 +
end

74. Functions and Pattern
Matching
defmodule MySum do
defp _sum(total, []), do: total
defp _sum(total, [head | tail]), do: _sum(total +
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_ﬁle.exs”) do
{ :ok, ﬁle } => 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
end

94. Macros
defmodule Plus do
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
{ sender, message } -> send sender, { :ok, "Hi
#{message}!"}
end
end
end

97. Concurrency
defmodule Spawnee do
def hi 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
{ sender, message } -> send sender, { :ok, "Hi #{message}!"}
end
end
end
pid = spawn(Spawnee, :hi, [])
send pid, { self, "Elixir" }
{ :ok, message } -> IO.puts message
end

99. Concurrency
defmodule Spawnee do
def hi do
{ sender, message } -> send sender, { :ok, "Hi #{message}!"}
end
end
end
pid = spawn(Spawnee, :hi, [])
send pid, { self, "Elixir" }
{ :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
{ :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
{ :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
{ :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!