SlideShare a Scribd company logo
1 of 55
Download to read offline
ELIXIR
PROGRAMMING LANGUAGE
|> Lack of memory -> Accurate manual allocation, but lost pieces of
memory + error-prone
|> CPU becomes faster -> GC (automatic memory management)
|> CPU doesn’t become faster, but with more cores –> Concurrent
execution, but shared resources
|> Synchronisation -> Hard to code + performance penalty
|> Better concurrent model and execution environment -> Erlang VM
(perfect for distributed software), but lack of metaprogramming,
polymorphism and first-class tooling in ecosystem
HISTORY
ELIXIR IS GREAT FOR WRITING
HIGHLY PARALLEL, RELIABLE
APPLICATIONS.
Jose Valim
ELIXIR SUPPORTED BY IDIOMS AND CONVENTIONS
|> Easy Concurrent (Actor Model)
|> Fault Tolerant
|> Functional Paradigm
|> Extensible & DSL
|> Metaprogramming
|> Leverage all Erlang legacy
ELIXIR
Immutable data is known data
|> No way to concurrence data mess
|> Because handle state gracefully
IMMUTABILITY
Performance Implications
|> Copying Data
|> Garbage Collection (per process)
TYPES
FUNCTION
RANGEATOMFLOATINTEGERBOOLEAN
PID REF
LIST TUPLE KEYWORD
LIST MAP BINARY
|> Integers Unlimited
|> Floating-Point Numbers IEEE 754
|> Only Integer Ranges
VALUE TYPES
1
# > 1
1_000_000_000
# > 1000000000
3.14
# > 3.14
2.99792458e8
# > 299792458.0
:atom
# > :atom
:"molecula"
# > :molecula
1..10
# > 1..10
true == :true
# > true
false == :false
# > true
nil
# > nil
~r/[aeiou]/
# > ~r/[aeiou]/
PATTERN MATCHING
list = [1, 2, 3]
# > [1, 2, 3]
[_, teas] = [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]]
# > [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]]
teas
# > ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]
[tea, tea] = [1, 2]
PATTERN MATCHING
list = [1, 2, 3]
# > [1, 2, 3]
[_, teas] = [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]]
# > [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]]
teas
# > ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]
[tea, tea] = [1, 2]
# > ** (MatchError) no match of right hand side value: [1, 2]
PATTERN MATCHING
list = [1, 2, 3]
# > [1, 2, 3]
[_, teas] = [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]]
# > [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]]
teas
# > ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]
[tea, tea] = [1, 2]
tea = "Puer"
# > "Puer"
"Puer"
# > "Puer"
tea = "Da Hong Pao"
# > "Da Hong Pao"
"Da Hong Pao"
# > "Da Hong Pao"
^tea = "Longjing"
# > ** (MatchError) no match of right hand side value: "Longjing"
# > ** (MatchError) no match of right hand side value: [1, 2]
SYSTEM TYPES
self
# > #PID<0.80.0>
pid = spawn fn -> "Hi" end
# > #PID<0.84.0>
COLLECTION TYPES
{1, :atom, "string", {:another, :tuple}}
# > {1, :atom, "string", {:another, :tuple}}
[1, :atom, "string", [:another, :list]]
# > [1, :atom, "string", [:another, :list]]
[first_name: "Menya", last_name: "Musashi"]
# > [first_name: "Menya", last_name: "Musashi"]
f = fn args -> "#{Keyword.get(args, :first_name)} #{Keyword.get(args, :last_name)}" end
# > #Function<6.52032458/1 in :erl_eval.expr/5>
f.(first_name: "Menya", last_name: "Musashi") #
# > "Menya Musashi"
%{1 => :atom, "string" => %{ another: :map}, "exp" <> "ressions" => 2 + 2}
# > %{1 => :atom, "expressions" => 4, "string" => %{another: :map}}
%{"key" => "value1", "key" => "value2"}
# > %{"key" => "value2"}
m = %{some_key: "some_value"}
# > %{some_key: "some_value"}
m[:some_key]
# > "some_value"
m.some_key # shortcut for getting value by symbol key
# > "some_value"
<<1, 2>> # 0000000100000010 – 2 bytes (by default)
# > <<1, 2>>
bitstring = <<1 :: size(2), 2 :: size(4)>> # 00010010 – 1 byte
# > <<18::size(6)>>
bit_size(bitstring)
# > 6
byte_size(bitstring)
# > 1
STRINGS
#{}N T XUTF-8 HEREDOC
"""
HERE
DOC
"""
# > " HEREn DOCn"
SIGIL
~c/abc/
# > 'abc'
~r/a.+z/
# > ~r/a.+z/
~s/"Menya Musashi"/
# > ""Menya Musashi""
~w<Something for nothing>
# > ["Something", "for", "nothing"]
~w[Something for nothing]s
# > ["Something", "for", "nothing"]
~w{Something for nothing}a
# > [:Something, :for, :nothing]
~w|Something for nothing|c
# > ['Something', 'for', 'nothing']
BINARIES
|> Bits List
b = <<1, 2, 3>> # 00000001 00000010 00000011
# > <<1, 2, 3>>
byte_size(b)
# > 3
bit_size(b)
# > 24
b = <<1::size(2), 2::size(3)>>
# > <<10::size(5)>>
byte_size(b)
# > 1
bit_size(b)
# > 5
<<16245::utf8>>
# > "㽵"
<<16245::unsigned-integer-size(12)>>
# > <<247, 5::size(4)>>
<<sign::size(1), exp::size(11), mantissa::size(52)>> =
<<3.14159::float>>
# > <<64, 9, 33, 249, 240, 27, 134, 110>>
(1 + mantissa / :math.pow(2, 52)) * :math.pow(2, exp - 1023)
# > 3.14159
STRINGS AS BINARIES
UTF-8 BINARY UTF-8 BINARY UTF-8 BINARY UTF-8 BINARY
String.length("㽵")
# > 1
byte_size("㽵")
# > 3
String.codepoints("Nou0308l")
# > ["N", "o", "̈", "l"]
String.graphemes("Nou0308l")
# > ["N", "ö", "l"]
to_string(<<97, 98, 99>>)
# > "abc"
<<97, 98, 99>>
# > “abc"
is_binary("abc")
# > true
CHARACTER LISTS
'abc'
# > 'abc'
List.to_tuple('abc')
# > {97, 98, 99}
[97, 98, 99]
# > 'abc'
?a
# > 97
is_list('abc')
# > true
|> In practice, char lists are used mostly when interfacing
with Erlang, in particular old libraries that do not accept
binaries as arguments
OPERATORS
"Menya" <> " Musashi"
# > "Menya Musashi"
<<97>> <> "bc"
# > "abc"
[2, "Puer"] ++ [4, "Da Hong Pao"]
# > [2, "Puer", 4, "Da Hong Pao"]
"Tieguanyin" in ["Tieguanyin", "Maofeng", "Biluochun"]
# > true
"Gyokuro" in ["Tieguanyin", "Maofeng", "Biluochun"]
# > false
DICTIONARIES
kwlist = [ tea: "Maofeng", tea: "Tieguanyin", fruit: "Apple" ]
# > [tea: "Maofeng", tea: "Tieguanyin", fruit: "Apple"]
kwlist[:tea]
# > "Maofeng"
map = %{ "alpha" => 1, "betta" => 2 }
# > %{"alpha" => 1, "betta" => 2}
map["alpha"]
# > 1
map["gamma"]
# > nil
map = %{ tea: "Maofeng", tea: "Tieguanyin", fruit: "Apple" }
# > %{fruit: "Apple", tea: "Tieguanyin"}
map.tea
# > "Tieguanyin"
map[:tea]
# > "Tieguanyin"
map[:juice]
# > nil
defmodule Tea do
defstruct name: "Puer", type: :fermented, area: "Yunnan"
end
%Tea{}
# > %Tea{area: "Yunnan", name: "Puer", type: :fermented}
tea = %Tea{name: "Tieguanyin", area: "Fujian"}
# > %Tea{area: "Fujian", name: "Tieguanyin", type: :fermented}
tea.name
# > "Tieguanyin"
MAP
KEYWORD
LIST
STRUCT
COMPREHENSIONS
MAPGENERATOR FILTER
list = [1, 2, 3, 4, 5, 6, 7, 8]
# > [1, 2, 3, 4, 5, 6, 7, 8]
for x <- list, y <- list, x >= y, rem(x * y, 10) == 0, do: {x, y}
# > [{5, 2}, {5, 4}, {6, 5}, {8, 5}]
for x <- ~w{b c}, into: %{ "a" => "A" }, do: { x, String.upcase(x) }
# > %{"a" => "A", "b" => "B", "c" => "C"}
ANONYMOUS FUNCTIONS
f = fn (parameter list) -> body end
f = fn (a, b) -> a + b end
# > #Function<12.52032458/2 in :erl_eval.expr/5>
f.(1, 2)
# > 3
swap = fn [a, b] -> [b, a] end
# > #Function<6.52032458/1 in :erl_eval.expr/5>
swap.([1, 2])
# > [2, 1]
foobar = fn
(0, 0) -> "FooBar"
(0, _) -> "Foo"
(_, 0) -> "Bar"
(_, _) -> "Nothing"
end
# > #Function<12.52032458/2 in :erl_eval.expr/5>
foobar.(1, 0)
# > "Bar"
f = fn -> fn -> "A" end end
# > #Function<20.52032458/0 in :erl_eval.expr/5>
f.().()
# > "A"
add = &(&1 + &2)
# > &:erlang.+/2
add.(1, 2)
# > 3
multiplier = 10
# > 10
Enum.map [1, 2, 3, 4], &(&1 * multiplier)
# > [10, 20, 30, 40]
NAMED FUNCTIONS
defmodule Tea do
def brew(tea, water_temperature  90)
def brew(tea, water_temperature) when tea == "Gyokuro" do
"Made in Japan. Brewing #{tea} (#{water_temperature} C)..."
end
def brew(tea, water_temperature) when tea == "Tieguanyin" do
"Made in Chaina. Brewing #{tea} (#{water_temperature} C)..."
end
def brew(tea, water_temperature) do
"Brewing #{tea} (#{water_temperature} C)..."
end
defp think(topic) do
"Thinking about #{topic}..."
end
end
Tea.brew("Puer")
# > "Brewing Puer (90 C)..."
Tea.brew("Gyokuro")
# > "Made in Japan. Brewing Gyokuro (90 C)..."
Tea.brew("Gyokuro", 60)
# > "Made in Japan. Brewing Gyokuro (60 C)..."
Tea.brew("Tieguanyin", 80)
# > "Made in Chaina. Brewing Tieguanyin (80 C)..."
Tea.think("Eternity") # Check spelling
# > ** (UndefinedFunctionError) function Tea.think/1 is
undefined or private
# > Tea.think("Eternity")
RECURSION
defmodule MyList do
def sum([]), do: 0
def sum([head | tail]), do: head + sum(tail)
end
list = [3, 2, 1]
# > [3, 2, 1]
sum = MyList.sum(list)
# > 6
|> Reducing algorithm
|> Mapping algorithm
PIPE OPERATOR
defmodule Tea do
defmodule Master do
def brew(tea), do: "Brewing #{tea} with optimal water temperature..."
end
def find(title), do: title
end
Tea.Master.brew(Tea.find("Puer"))
# > "Brewing Puer with optimal water temperature..."
"Puer" |> Tea.find |> Tea.Master.brew
# > "Brewing Puer with optimal water temperature..."
prepend_awesome = fn x -> "Awesome " <> x end
# > #Function<6.52032458/1 in :erl_eval.expr/5>
append_try_it = fn x -> x <> ", try it!" end
# > #Function<6.52032458/1 in :erl_eval.expr/5>
"Elixir" |> prepend_awesome |> append_try_it # Exception
# > ** (CompileError) iex:8: undefined function append_try_it/1
# > (elixir) expanding macro: Kernel.|>/2
# > iex:8: (file)
"Elixir" |> prepend_awesome.() |> append_try_it.()
# > "Awesome Elixir, try it!"
FROM SOURCE CODE TO VIRTUAL MACHINE
.EXS
.EX
ELIXIR
COMPILER
BYTECODE
.BEAM
HDD
ERLANG VM
MODULES
defmodule Tea.Container do
def prepare do
IO.puts "Prepare container..."
end
end
defmodule Tea.Pot do
@material "yixing clay" # mostly use as a constant, can't be
defined inside function definition
def prepare do
IO.puts "Prepare pot from #{@material}..."
end
end
defmodule Tea.Bowl do
def prepare do
IO.puts "Prepare bowl..."
end
end
defmodule Tea.Spoon do
def prepare do
IO.puts "Prepare spoon..."
end
end
defmodule Tea.Utensils do
alias Tea.Container
alias Tea.{Pot, Bowl}
alias Tea.Spoon, as: Scoop
def prepare do
Container.prepare
Pot.prepare
Bowl.prepare
Scoop.prepare
end
end
defmodule Tea.Master do
def prepare(utensils) do
utensils.prepare
end
def choose_tea do
IO.puts "Choose tea sort..."
end
def brew do
IO.puts "Brew tea..."
end
def taste do
IO.puts "Thruuup-thruup... so tasty!"
end
end
defmodule Tea.Style do
defmacro style(name) do
quote do
IO.puts "Tea story: #{unquote(name)} style"
end
end
end
defmodule Tea.Ceremony do
import Tea.Style
alias Tea.Master
alias Tea.Utensils
style :chaineese
def run do
Master.prepare(Utensils)
Master.choose_tea
Master.brew
Master.taste
end
end
Tea.Ceremony.run
# > Prepare container...
# > Prepare pot from yixing clay...
# > Prepare bowl...
# > Prepare spoon...
# > Choose tea sort...
# > Brew tea...
# > Thruuup-thruup... so tasty!
# > :ok
|> Duck Typing
|> Type = Primitive implementation + Modules
|> @type
|> @spec
TYPE SUMMARY
PROTOCOLS
defprotocol CaesarCypher do
def encrypt(stringlike, shift)
def rot13(stringlike)
end
defimpl CaesarCypher, for: List do
def encrypt([], _shift), do: []
def encrypt([head | tail], shift) do
[rem((head - 97 + shift), 26) + 97 | encrypt(tail, shift)]
end
def rot13(list), do: encrypt(list, 13)
end
defimpl CaesarCypher, for: BitString do
def encrypt(string, shift) do
to_charlist(string) |> _encrypt(shift) |> to_string
end
def rot13(string), do: encrypt(string, 13)
defp _encrypt([], _shift), do: []
defp _encrypt([head | tail], shift) do
[rem((head - 97 + shift), 26) + 97 | _encrypt(tail, shift)]
end
end
CaesarCypher.encrypt('zappa', 1)
# > 'abqqb'
CaesarCypher.rot13('zappa')
# > 'mnccn'
CaesarCypher.encrypt("zappa", 1)
# > "abqqb"
CaesarCypher.rot13("zappa")
# > "mnccn"
|> Elixir is lexically scoped
|> Basic unit – function body
|> Module has it’s own non visible for functions scope
|> Comprehensions and with create a separate lexical scope
SCOPES
MACROS
|> Language extension
|> Never use a macro when you can use a function
ELIXIR
SOURCE
CODE
ELIXIR
MACRO
EXPANSION
ELIXIR
COMPILER
COMPILE TIME
BEAM
BYTECODE
CORE
ERLANG
MACROS
defmodule Meta do
defmacro define_methods(names) do
IO.puts("Compile time: #{inspect(names)}")
for name <- names do
quote do
def unquote(name)() do
IO.puts("Run time: #{inspect(unquote(name))}")
"Hi, from #{unquote(name)} method"
end
end
end
end
end
defmodule M do
import Meta
define_methods [:alpha, :beta]
end
# > Compile time: [:alpha, :beta]
M.alpha
# > Run time: :alpha
# > "Hi, from alpha method"
M.beta
# > Run time: :beta
# > "Hi, from beta method"
MIX
Build tool
|>Elixir built-in
|>Create application
|>Compile application
|>Test application (ExUnit)
|>Manage application dependencies
|>Environments (MIX_ENV: dev, test, prod)
mix new tea_master
mix deps.get
mix phoenix.new
What about concurrency?
PROCESSES
|> Lightweight
|> Isolated
|> Actors
P1
MESSAGE
MESSAGE
THREAD
P2
PROCESS IS NOT ONLY ABOUT
CONCURRENCY, BUT ALSO ABOUT
DISTRIBUTION AND FAULT-TOLERANCE.
Jose Valim
FAIL FAST, ALLOW SUPERVISOR TO RESTART OR BURY FAILED PROCESS
PROCESSES
P1 P2
p1 = spawn(fn ->
end)
# > #PID<0.86.0>
Process.alive?(p1)
# > false
p2 = self()
# > #PID<0.95.0>
Process.alive?(p2)
# > true
PROCESSES
P1 P2
p1 = spawn(fn ->
end)
# > #PID<0.86.0>
Process.alive?(p1)
# > false
p2 = self()
# > #PID<0.95.0>
Process.alive?(p2)
# > true
PROCESSES COMMUNICATION
P1 P2
p1 = self()
# > #PID<0.81.0>
msg = "Ping"
# > "Ping"
p2 = spawn(fn ->
end)
# > Ping
# > #PID<0.101.0>
receive do
msg -> IO.puts(msg)
end
# > Pong
# > :ok
IO.puts(msg)
send(p1, "Pong")
PROCESSES COMMUNICATION
P1 P2
p1 = self()
# > #PID<0.81.0>
msg = "Ping"
# > "Ping"
p2 = spawn(fn ->
end)
# > Ping
# > #PID<0.101.0>
receive do
msg -> IO.puts(msg)
end
# > Pong
# > :ok
IO.puts(msg)
send(p1, "Pong")
PROCESSES COMMUNICATION
P1 P2
p1 = self()
# > #PID<0.81.0>
msg = "Ping"
# > "Ping"
p2 = spawn(fn ->
end)
# > Ping
# > #PID<0.101.0>
receive do
msg -> IO.puts(msg)
end
# > Pong
# > :ok
MESSAGE
IO.puts(msg)
send(p1, "Pong")
PROCESSES LINKING
P1 P2
spawn_link(fn ->
end)
P1 P2p2 = spawn(fn ->
end)
# > #PID<0.113.0>
Process.link(p2)
# > true
raise "Dad, I'm dead"
# > ** (EXIT from #PID<0.81.0>) an
exception was raised:
# > ** (RuntimeError) Dad, I'm
dead
:timer.sleep(1000)
raise "Mom, I'm dead”
# > ** (EXIT from #PID<0.81.0>) an
exception was raised:
# > ** (RuntimeError) Mom, I'm
dead
# > :ok
PROCESSES LINKING
P1 P2
spawn_link(fn ->
end)
P1 P2p2 = spawn(fn ->
end)
# > #PID<0.113.0>
Process.link(p2)
# > true
raise "Dad, I'm dead"
# > ** (EXIT from #PID<0.81.0>) an
exception was raised:
# > ** (RuntimeError) Dad, I'm
dead
:timer.sleep(1000)
raise "Mom, I'm dead”
# > ** (EXIT from #PID<0.81.0>) an
exception was raised:
# > ** (RuntimeError) Mom, I'm
dead
# > :ok
PROCESSES LINKING
P1 P2
spawn_link(fn ->
end)
P1 P2p2 = spawn(fn ->
end)
# > #PID<0.113.0>
Process.link(p2)
# > true
raise "Dad, I'm dead"
# > ** (EXIT from #PID<0.81.0>) an
exception was raised:
# > ** (RuntimeError) Dad, I'm
dead
:timer.sleep(1000)
raise "Mom, I'm dead”
# > ** (EXIT from #PID<0.81.0>) an
exception was raised:
# > ** (RuntimeError) Mom, I'm
dead
# > :ok
L
L
L
L
|> Application discovery
|> Failure detection
|> Processes management
|> Hot code swapping
|> Server structure
OTP
ERLANG MNESIA
L
L
L
L
OTP+ + =
A
A
L
L
L
L
|> Application discovery
|> Failure detection
|> Processes management
|> Hot code swapping
|> Server structure
OTP
ERLANG MNESIA
L
L
L
L
OTP+ + =
A
A
P
P P
|> Task (performs async work)
|> Agent (holds state)
|> GenServer (general purpose client-server scaffold)
|> Supervisor
OTHER CONCURRENT ABSTRACTIONS
TASK
defmodule Tea.Master do
def brew do
IO.puts "Brewing tea..."
:timer.sleep(1000)
IO.puts "Tea is ready!"
"a cup of tea"
end
end
IO.puts "[Tea Master] Please sit down and take a rest"
IO.puts "[Tea Master] I need some time to brew the tea"
worker = Task.async(fn -> Tea.Master.brew() end)
IO.puts "[Guest] I have to clean my mind"
result = Task.await(worker)
IO.puts "The result is #{result}"
# > [Tea Master] Please sit down and take a rest
# > [Tea Master] I need some time to brew the tea
# > [Guest] I have to clean my mind
# > Brewing tea...
# > Tea is ready!
# > The result is a cup of tea
AGENT
{ :ok, wisdom } = Agent.start(fn -> "Elixir" end)
# > {:ok, #PID<0.83.0>}
Agent.get(wisdom, &(&1))
# > "Elixir"
Agent.update(wisdom, &(&1 <> "is awesome"))
# > :ok
Agent.get(wisdom, &(&1))
# > "Elixiris awesome"
# > nil
Agent.start(fn -> [] end, name: Fridge)
# > {:ok, #PID<0.89.0>}
Agent.update(Fridge, &(["milk" | &1]))
# > :ok
Agent.get(Fridge, &(&1))
# > ["milk"]
Agent.update(Fridge, &(["butter" | &1]))
# > :ok
Agent.get(Fridge, &(&1))
# > ["butter", "milk"]
GENSERVER
defmodule Stack do
use GenServer
# Client API
def start_link do
GenServer.start_link(__MODULE__, :ok, [])
end
def push(pid, item) do
GenServer.cast(pid, {:push, item})
end
def pop(pid) do
GenServer.call(pid, :pop)
end
# Server API
def handle_call(:pop, _from, state) do
[item | next_state] = state
{:reply, item, next_state}
end
def handle_cast({:push, item}, state) do
next_state = [item | state]
{:noreply, next_state}
end
end
{:ok, stack} = Stack.start_link
# > {:ok, #PID<0.117.0>}
Stack.push(stack, "milk")
# > :ok
Stack.push(stack, "butter")
# > :ok
Stack.pop(stack)
# > "butter"
Stack.pop(stack)
# > "milk"
SUPERVISOR
defmodule Mathex do
use Application
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
import Supervisor.Spec
# Define workers and child supervisors to be supervised
children = [
supervisor(Mathex.Repo, []),
supervisor(Mathex.Endpoint, []),
# Start your own worker by calling: Mathex.Worker.start_link(arg1, arg2, arg3)
# worker(Mathex.Worker, [arg1, arg2, arg3]),
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Mathex.Supervisor]
Supervisor.start_link(children, opts)
end
# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
def config_change(changed, _new, removed) do
Mathex.Endpoint.config_change(changed, removed)
:ok
end
end
APPLICATION
APPLICATION
P1
P1 P1
UMBRELLA PROJECTS
☂
APPLICATION
P1
P1 P1
APPLICATION
P1
P1 P1
DOCUMENTATION
|>First-class citizen
|>h helper
|>@docmodule
|>@doc
|>exdoc
|>doctets
|>README Driven Development
defmodule YAC do
@moduledoc """
Yet Another Calculator
"""
@doc """
Sum two numbers
## Examples
iex> sum(1, 2)
3
"""
def sum(a, b) do
a + b
end
end
|> https://learnxinyminutes.com/docs/elixir
|> http://elixir-lang.org
|> http://blog.plataformatec.com.br/2015/06/elixir-in-times-
of-microservices
|> http://howistart.org/posts/elixir/1
|> https://www.youtube.com/watch?v=L0qC97ytMjQ
RESOURCES
?

More Related Content

What's hot

Python data structures
Python data structuresPython data structures
Python data structuresHarry Potter
 
PLOTCON NYC: Behind Every Great Plot There's a Great Deal of Wrangling
PLOTCON NYC: Behind Every Great Plot There's a Great Deal of WranglingPLOTCON NYC: Behind Every Great Plot There's a Great Deal of Wrangling
PLOTCON NYC: Behind Every Great Plot There's a Great Deal of WranglingPlotly
 
令和から本気出す
令和から本気出す令和から本気出す
令和から本気出すTakashi Kitano
 
好みの日本酒を呑みたい! 〜さけのわデータで探す自分好みの酒〜
好みの日本酒を呑みたい! 〜さけのわデータで探す自分好みの酒〜好みの日本酒を呑みたい! 〜さけのわデータで探す自分好みの酒〜
好みの日本酒を呑みたい! 〜さけのわデータで探す自分好みの酒〜Takashi Kitano
 
How fast ist it really? Benchmarking in practice
How fast ist it really? Benchmarking in practiceHow fast ist it really? Benchmarking in practice
How fast ist it really? Benchmarking in practiceTobias Pfeiffer
 
{shiny}と{leaflet}による地図アプリ開発Tips
{shiny}と{leaflet}による地図アプリ開発Tips{shiny}と{leaflet}による地図アプリ開発Tips
{shiny}と{leaflet}による地図アプリ開発TipsTakashi Kitano
 
{tidytext}と{RMeCab}によるモダンな日本語テキスト分析
{tidytext}と{RMeCab}によるモダンな日本語テキスト分析{tidytext}と{RMeCab}によるモダンな日本語テキスト分析
{tidytext}と{RMeCab}によるモダンな日本語テキスト分析Takashi Kitano
 
جلسه سوم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه سوم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲جلسه سوم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه سوم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲Mohammad Reza Kamalifard
 
Clustering com numpy e cython
Clustering com numpy e cythonClustering com numpy e cython
Clustering com numpy e cythonAnderson Dantas
 
Ruby nooks & crannies
Ruby nooks & cranniesRuby nooks & crannies
Ruby nooks & cranniesKerry Buckley
 
Introduction to Search Systems - ScaleConf Colombia 2017
Introduction to Search Systems - ScaleConf Colombia 2017Introduction to Search Systems - ScaleConf Colombia 2017
Introduction to Search Systems - ScaleConf Colombia 2017Toria Gibbs
 

What's hot (16)

Python data structures
Python data structuresPython data structures
Python data structures
 
PLOTCON NYC: Behind Every Great Plot There's a Great Deal of Wrangling
PLOTCON NYC: Behind Every Great Plot There's a Great Deal of WranglingPLOTCON NYC: Behind Every Great Plot There's a Great Deal of Wrangling
PLOTCON NYC: Behind Every Great Plot There's a Great Deal of Wrangling
 
令和から本気出す
令和から本気出す令和から本気出す
令和から本気出す
 
好みの日本酒を呑みたい! 〜さけのわデータで探す自分好みの酒〜
好みの日本酒を呑みたい! 〜さけのわデータで探す自分好みの酒〜好みの日本酒を呑みたい! 〜さけのわデータで探す自分好みの酒〜
好みの日本酒を呑みたい! 〜さけのわデータで探す自分好みの酒〜
 
How fast ist it really? Benchmarking in practice
How fast ist it really? Benchmarking in practiceHow fast ist it really? Benchmarking in practice
How fast ist it really? Benchmarking in practice
 
{shiny}と{leaflet}による地図アプリ開発Tips
{shiny}と{leaflet}による地図アプリ開発Tips{shiny}と{leaflet}による地図アプリ開発Tips
{shiny}と{leaflet}による地図アプリ開発Tips
 
{tidytext}と{RMeCab}によるモダンな日本語テキスト分析
{tidytext}と{RMeCab}によるモダンな日本語テキスト分析{tidytext}と{RMeCab}によるモダンな日本語テキスト分析
{tidytext}と{RMeCab}によるモダンな日本語テキスト分析
 
جلسه سوم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه سوم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲جلسه سوم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه سوم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
 
The Magic Of Elixir
The Magic Of ElixirThe Magic Of Elixir
The Magic Of Elixir
 
PubNative Tracker
PubNative TrackerPubNative Tracker
PubNative Tracker
 
Clustering com numpy e cython
Clustering com numpy e cythonClustering com numpy e cython
Clustering com numpy e cython
 
Python 1
Python 1Python 1
Python 1
 
Ruby things
Ruby thingsRuby things
Ruby things
 
Intro
IntroIntro
Intro
 
Ruby nooks & crannies
Ruby nooks & cranniesRuby nooks & crannies
Ruby nooks & crannies
 
Introduction to Search Systems - ScaleConf Colombia 2017
Introduction to Search Systems - ScaleConf Colombia 2017Introduction to Search Systems - ScaleConf Colombia 2017
Introduction to Search Systems - ScaleConf Colombia 2017
 

Similar to ELIXIR PROGRAMMING LANGUAGE FEATURES AND CONCEPTS

Τα Πολύ Βασικά για την Python
Τα Πολύ Βασικά για την PythonΤα Πολύ Βασικά για την Python
Τα Πολύ Βασικά για την PythonMoses Boudourides
 
Learn 90% of Python in 90 Minutes
Learn 90% of Python in 90 MinutesLearn 90% of Python in 90 Minutes
Learn 90% of Python in 90 MinutesMatt Harrison
 
python chapter 1
python chapter 1python chapter 1
python chapter 1Raghu nath
 
Python chapter 2
Python chapter 2Python chapter 2
Python chapter 2Raghu nath
 
Elixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsElixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsHéla Ben Khalfallah
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a bossgsterndale
 
Useful javascript
Useful javascriptUseful javascript
Useful javascriptLei Kang
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick touraztack
 
Python language data types
Python language data typesPython language data types
Python language data typesHarry Potter
 
Python language data types
Python language data typesPython language data types
Python language data typesHoang Nguyen
 
Python language data types
Python language data typesPython language data types
Python language data typesLuis Goldster
 
Python language data types
Python language data typesPython language data types
Python language data typesTony Nguyen
 
Python language data types
Python language data typesPython language data types
Python language data typesFraboni Ec
 
Python language data types
Python language data typesPython language data types
Python language data typesJames Wong
 
Python language data types
Python language data typesPython language data types
Python language data typesYoung Alista
 
Python fundamentals - basic | WeiYuan
Python fundamentals - basic | WeiYuanPython fundamentals - basic | WeiYuan
Python fundamentals - basic | WeiYuanWei-Yuan Chang
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a ElixirSvet Ivantchev
 

Similar to ELIXIR PROGRAMMING LANGUAGE FEATURES AND CONCEPTS (20)

Τα Πολύ Βασικά για την Python
Τα Πολύ Βασικά για την PythonΤα Πολύ Βασικά για την Python
Τα Πολύ Βασικά για την Python
 
Learn 90% of Python in 90 Minutes
Learn 90% of Python in 90 MinutesLearn 90% of Python in 90 Minutes
Learn 90% of Python in 90 Minutes
 
python chapter 1
python chapter 1python chapter 1
python chapter 1
 
Python chapter 2
Python chapter 2Python chapter 2
Python chapter 2
 
Elixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental ConceptsElixir in a nutshell - Fundamental Concepts
Elixir in a nutshell - Fundamental Concepts
 
R programming language
R programming languageR programming language
R programming language
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a boss
 
Useful javascript
Useful javascriptUseful javascript
Useful javascript
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick tour
 
Python language data types
Python language data typesPython language data types
Python language data types
 
Python language data types
Python language data typesPython language data types
Python language data types
 
Python language data types
Python language data typesPython language data types
Python language data types
 
Python language data types
Python language data typesPython language data types
Python language data types
 
Python language data types
Python language data typesPython language data types
Python language data types
 
Python language data types
Python language data typesPython language data types
Python language data types
 
Python language data types
Python language data typesPython language data types
Python language data types
 
Python tutorial
Python tutorialPython tutorial
Python tutorial
 
Python fundamentals - basic | WeiYuan
Python fundamentals - basic | WeiYuanPython fundamentals - basic | WeiYuan
Python fundamentals - basic | WeiYuan
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a Elixir
 
Ruby 1.9
Ruby 1.9Ruby 1.9
Ruby 1.9
 

Recently uploaded

SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 

Recently uploaded (20)

SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 

ELIXIR PROGRAMMING LANGUAGE FEATURES AND CONCEPTS

  • 2. |> Lack of memory -> Accurate manual allocation, but lost pieces of memory + error-prone |> CPU becomes faster -> GC (automatic memory management) |> CPU doesn’t become faster, but with more cores –> Concurrent execution, but shared resources |> Synchronisation -> Hard to code + performance penalty |> Better concurrent model and execution environment -> Erlang VM (perfect for distributed software), but lack of metaprogramming, polymorphism and first-class tooling in ecosystem HISTORY
  • 3.
  • 4. ELIXIR IS GREAT FOR WRITING HIGHLY PARALLEL, RELIABLE APPLICATIONS. Jose Valim ELIXIR SUPPORTED BY IDIOMS AND CONVENTIONS
  • 5. |> Easy Concurrent (Actor Model) |> Fault Tolerant |> Functional Paradigm |> Extensible & DSL |> Metaprogramming |> Leverage all Erlang legacy ELIXIR
  • 6. Immutable data is known data |> No way to concurrence data mess |> Because handle state gracefully IMMUTABILITY Performance Implications |> Copying Data |> Garbage Collection (per process)
  • 8. |> Integers Unlimited |> Floating-Point Numbers IEEE 754 |> Only Integer Ranges VALUE TYPES 1 # > 1 1_000_000_000 # > 1000000000 3.14 # > 3.14 2.99792458e8 # > 299792458.0 :atom # > :atom :"molecula" # > :molecula 1..10 # > 1..10 true == :true # > true false == :false # > true nil # > nil ~r/[aeiou]/ # > ~r/[aeiou]/
  • 9. PATTERN MATCHING list = [1, 2, 3] # > [1, 2, 3] [_, teas] = [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]] # > [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]] teas # > ["Puer", "Da Hong Pao", "Longjing", "Biluochun"] [tea, tea] = [1, 2]
  • 10. PATTERN MATCHING list = [1, 2, 3] # > [1, 2, 3] [_, teas] = [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]] # > [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]] teas # > ["Puer", "Da Hong Pao", "Longjing", "Biluochun"] [tea, tea] = [1, 2] # > ** (MatchError) no match of right hand side value: [1, 2]
  • 11. PATTERN MATCHING list = [1, 2, 3] # > [1, 2, 3] [_, teas] = [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]] # > [3, ["Puer", "Da Hong Pao", "Longjing", "Biluochun"]] teas # > ["Puer", "Da Hong Pao", "Longjing", "Biluochun"] [tea, tea] = [1, 2] tea = "Puer" # > "Puer" "Puer" # > "Puer" tea = "Da Hong Pao" # > "Da Hong Pao" "Da Hong Pao" # > "Da Hong Pao" ^tea = "Longjing" # > ** (MatchError) no match of right hand side value: "Longjing" # > ** (MatchError) no match of right hand side value: [1, 2]
  • 12. SYSTEM TYPES self # > #PID<0.80.0> pid = spawn fn -> "Hi" end # > #PID<0.84.0>
  • 13. COLLECTION TYPES {1, :atom, "string", {:another, :tuple}} # > {1, :atom, "string", {:another, :tuple}} [1, :atom, "string", [:another, :list]] # > [1, :atom, "string", [:another, :list]] [first_name: "Menya", last_name: "Musashi"] # > [first_name: "Menya", last_name: "Musashi"] f = fn args -> "#{Keyword.get(args, :first_name)} #{Keyword.get(args, :last_name)}" end # > #Function<6.52032458/1 in :erl_eval.expr/5> f.(first_name: "Menya", last_name: "Musashi") # # > "Menya Musashi" %{1 => :atom, "string" => %{ another: :map}, "exp" <> "ressions" => 2 + 2} # > %{1 => :atom, "expressions" => 4, "string" => %{another: :map}} %{"key" => "value1", "key" => "value2"} # > %{"key" => "value2"} m = %{some_key: "some_value"} # > %{some_key: "some_value"} m[:some_key] # > "some_value" m.some_key # shortcut for getting value by symbol key # > "some_value" <<1, 2>> # 0000000100000010 – 2 bytes (by default) # > <<1, 2>> bitstring = <<1 :: size(2), 2 :: size(4)>> # 00010010 – 1 byte # > <<18::size(6)>> bit_size(bitstring) # > 6 byte_size(bitstring) # > 1
  • 14. STRINGS #{}N T XUTF-8 HEREDOC """ HERE DOC """ # > " HEREn DOCn" SIGIL ~c/abc/ # > 'abc' ~r/a.+z/ # > ~r/a.+z/ ~s/"Menya Musashi"/ # > ""Menya Musashi"" ~w<Something for nothing> # > ["Something", "for", "nothing"] ~w[Something for nothing]s # > ["Something", "for", "nothing"] ~w{Something for nothing}a # > [:Something, :for, :nothing] ~w|Something for nothing|c # > ['Something', 'for', 'nothing']
  • 15. BINARIES |> Bits List b = <<1, 2, 3>> # 00000001 00000010 00000011 # > <<1, 2, 3>> byte_size(b) # > 3 bit_size(b) # > 24 b = <<1::size(2), 2::size(3)>> # > <<10::size(5)>> byte_size(b) # > 1 bit_size(b) # > 5 <<16245::utf8>> # > "㽵" <<16245::unsigned-integer-size(12)>> # > <<247, 5::size(4)>> <<sign::size(1), exp::size(11), mantissa::size(52)>> = <<3.14159::float>> # > <<64, 9, 33, 249, 240, 27, 134, 110>> (1 + mantissa / :math.pow(2, 52)) * :math.pow(2, exp - 1023) # > 3.14159
  • 16. STRINGS AS BINARIES UTF-8 BINARY UTF-8 BINARY UTF-8 BINARY UTF-8 BINARY String.length("㽵") # > 1 byte_size("㽵") # > 3 String.codepoints("Nou0308l") # > ["N", "o", "̈", "l"] String.graphemes("Nou0308l") # > ["N", "ö", "l"] to_string(<<97, 98, 99>>) # > "abc" <<97, 98, 99>> # > “abc" is_binary("abc") # > true
  • 17. CHARACTER LISTS 'abc' # > 'abc' List.to_tuple('abc') # > {97, 98, 99} [97, 98, 99] # > 'abc' ?a # > 97 is_list('abc') # > true |> In practice, char lists are used mostly when interfacing with Erlang, in particular old libraries that do not accept binaries as arguments
  • 18. OPERATORS "Menya" <> " Musashi" # > "Menya Musashi" <<97>> <> "bc" # > "abc" [2, "Puer"] ++ [4, "Da Hong Pao"] # > [2, "Puer", 4, "Da Hong Pao"] "Tieguanyin" in ["Tieguanyin", "Maofeng", "Biluochun"] # > true "Gyokuro" in ["Tieguanyin", "Maofeng", "Biluochun"] # > false
  • 19. DICTIONARIES kwlist = [ tea: "Maofeng", tea: "Tieguanyin", fruit: "Apple" ] # > [tea: "Maofeng", tea: "Tieguanyin", fruit: "Apple"] kwlist[:tea] # > "Maofeng" map = %{ "alpha" => 1, "betta" => 2 } # > %{"alpha" => 1, "betta" => 2} map["alpha"] # > 1 map["gamma"] # > nil map = %{ tea: "Maofeng", tea: "Tieguanyin", fruit: "Apple" } # > %{fruit: "Apple", tea: "Tieguanyin"} map.tea # > "Tieguanyin" map[:tea] # > "Tieguanyin" map[:juice] # > nil defmodule Tea do defstruct name: "Puer", type: :fermented, area: "Yunnan" end %Tea{} # > %Tea{area: "Yunnan", name: "Puer", type: :fermented} tea = %Tea{name: "Tieguanyin", area: "Fujian"} # > %Tea{area: "Fujian", name: "Tieguanyin", type: :fermented} tea.name # > "Tieguanyin" MAP KEYWORD LIST STRUCT
  • 20. COMPREHENSIONS MAPGENERATOR FILTER list = [1, 2, 3, 4, 5, 6, 7, 8] # > [1, 2, 3, 4, 5, 6, 7, 8] for x <- list, y <- list, x >= y, rem(x * y, 10) == 0, do: {x, y} # > [{5, 2}, {5, 4}, {6, 5}, {8, 5}] for x <- ~w{b c}, into: %{ "a" => "A" }, do: { x, String.upcase(x) } # > %{"a" => "A", "b" => "B", "c" => "C"}
  • 21. ANONYMOUS FUNCTIONS f = fn (parameter list) -> body end f = fn (a, b) -> a + b end # > #Function<12.52032458/2 in :erl_eval.expr/5> f.(1, 2) # > 3 swap = fn [a, b] -> [b, a] end # > #Function<6.52032458/1 in :erl_eval.expr/5> swap.([1, 2]) # > [2, 1] foobar = fn (0, 0) -> "FooBar" (0, _) -> "Foo" (_, 0) -> "Bar" (_, _) -> "Nothing" end # > #Function<12.52032458/2 in :erl_eval.expr/5> foobar.(1, 0) # > "Bar" f = fn -> fn -> "A" end end # > #Function<20.52032458/0 in :erl_eval.expr/5> f.().() # > "A" add = &(&1 + &2) # > &:erlang.+/2 add.(1, 2) # > 3 multiplier = 10 # > 10 Enum.map [1, 2, 3, 4], &(&1 * multiplier) # > [10, 20, 30, 40]
  • 22. NAMED FUNCTIONS defmodule Tea do def brew(tea, water_temperature 90) def brew(tea, water_temperature) when tea == "Gyokuro" do "Made in Japan. Brewing #{tea} (#{water_temperature} C)..." end def brew(tea, water_temperature) when tea == "Tieguanyin" do "Made in Chaina. Brewing #{tea} (#{water_temperature} C)..." end def brew(tea, water_temperature) do "Brewing #{tea} (#{water_temperature} C)..." end defp think(topic) do "Thinking about #{topic}..." end end Tea.brew("Puer") # > "Brewing Puer (90 C)..." Tea.brew("Gyokuro") # > "Made in Japan. Brewing Gyokuro (90 C)..." Tea.brew("Gyokuro", 60) # > "Made in Japan. Brewing Gyokuro (60 C)..." Tea.brew("Tieguanyin", 80) # > "Made in Chaina. Brewing Tieguanyin (80 C)..." Tea.think("Eternity") # Check spelling # > ** (UndefinedFunctionError) function Tea.think/1 is undefined or private # > Tea.think("Eternity")
  • 23. RECURSION defmodule MyList do def sum([]), do: 0 def sum([head | tail]), do: head + sum(tail) end list = [3, 2, 1] # > [3, 2, 1] sum = MyList.sum(list) # > 6 |> Reducing algorithm |> Mapping algorithm
  • 24. PIPE OPERATOR defmodule Tea do defmodule Master do def brew(tea), do: "Brewing #{tea} with optimal water temperature..." end def find(title), do: title end Tea.Master.brew(Tea.find("Puer")) # > "Brewing Puer with optimal water temperature..." "Puer" |> Tea.find |> Tea.Master.brew # > "Brewing Puer with optimal water temperature..." prepend_awesome = fn x -> "Awesome " <> x end # > #Function<6.52032458/1 in :erl_eval.expr/5> append_try_it = fn x -> x <> ", try it!" end # > #Function<6.52032458/1 in :erl_eval.expr/5> "Elixir" |> prepend_awesome |> append_try_it # Exception # > ** (CompileError) iex:8: undefined function append_try_it/1 # > (elixir) expanding macro: Kernel.|>/2 # > iex:8: (file) "Elixir" |> prepend_awesome.() |> append_try_it.() # > "Awesome Elixir, try it!"
  • 25. FROM SOURCE CODE TO VIRTUAL MACHINE .EXS .EX ELIXIR COMPILER BYTECODE .BEAM HDD ERLANG VM
  • 26. MODULES defmodule Tea.Container do def prepare do IO.puts "Prepare container..." end end defmodule Tea.Pot do @material "yixing clay" # mostly use as a constant, can't be defined inside function definition def prepare do IO.puts "Prepare pot from #{@material}..." end end defmodule Tea.Bowl do def prepare do IO.puts "Prepare bowl..." end end defmodule Tea.Spoon do def prepare do IO.puts "Prepare spoon..." end end defmodule Tea.Utensils do alias Tea.Container alias Tea.{Pot, Bowl} alias Tea.Spoon, as: Scoop def prepare do Container.prepare Pot.prepare Bowl.prepare Scoop.prepare end end defmodule Tea.Master do def prepare(utensils) do utensils.prepare end def choose_tea do IO.puts "Choose tea sort..." end def brew do IO.puts "Brew tea..." end def taste do IO.puts "Thruuup-thruup... so tasty!" end end defmodule Tea.Style do defmacro style(name) do quote do IO.puts "Tea story: #{unquote(name)} style" end end end defmodule Tea.Ceremony do import Tea.Style alias Tea.Master alias Tea.Utensils style :chaineese def run do Master.prepare(Utensils) Master.choose_tea Master.brew Master.taste end end Tea.Ceremony.run # > Prepare container... # > Prepare pot from yixing clay... # > Prepare bowl... # > Prepare spoon... # > Choose tea sort... # > Brew tea... # > Thruuup-thruup... so tasty! # > :ok
  • 27. |> Duck Typing |> Type = Primitive implementation + Modules |> @type |> @spec TYPE SUMMARY
  • 28. PROTOCOLS defprotocol CaesarCypher do def encrypt(stringlike, shift) def rot13(stringlike) end defimpl CaesarCypher, for: List do def encrypt([], _shift), do: [] def encrypt([head | tail], shift) do [rem((head - 97 + shift), 26) + 97 | encrypt(tail, shift)] end def rot13(list), do: encrypt(list, 13) end defimpl CaesarCypher, for: BitString do def encrypt(string, shift) do to_charlist(string) |> _encrypt(shift) |> to_string end def rot13(string), do: encrypt(string, 13) defp _encrypt([], _shift), do: [] defp _encrypt([head | tail], shift) do [rem((head - 97 + shift), 26) + 97 | _encrypt(tail, shift)] end end CaesarCypher.encrypt('zappa', 1) # > 'abqqb' CaesarCypher.rot13('zappa') # > 'mnccn' CaesarCypher.encrypt("zappa", 1) # > "abqqb" CaesarCypher.rot13("zappa") # > "mnccn"
  • 29. |> Elixir is lexically scoped |> Basic unit – function body |> Module has it’s own non visible for functions scope |> Comprehensions and with create a separate lexical scope SCOPES
  • 30. MACROS |> Language extension |> Never use a macro when you can use a function ELIXIR SOURCE CODE ELIXIR MACRO EXPANSION ELIXIR COMPILER COMPILE TIME BEAM BYTECODE CORE ERLANG
  • 31. MACROS defmodule Meta do defmacro define_methods(names) do IO.puts("Compile time: #{inspect(names)}") for name <- names do quote do def unquote(name)() do IO.puts("Run time: #{inspect(unquote(name))}") "Hi, from #{unquote(name)} method" end end end end end defmodule M do import Meta define_methods [:alpha, :beta] end # > Compile time: [:alpha, :beta] M.alpha # > Run time: :alpha # > "Hi, from alpha method" M.beta # > Run time: :beta # > "Hi, from beta method"
  • 32. MIX Build tool |>Elixir built-in |>Create application |>Compile application |>Test application (ExUnit) |>Manage application dependencies |>Environments (MIX_ENV: dev, test, prod) mix new tea_master mix deps.get mix phoenix.new
  • 34. PROCESSES |> Lightweight |> Isolated |> Actors P1 MESSAGE MESSAGE THREAD P2
  • 35. PROCESS IS NOT ONLY ABOUT CONCURRENCY, BUT ALSO ABOUT DISTRIBUTION AND FAULT-TOLERANCE. Jose Valim FAIL FAST, ALLOW SUPERVISOR TO RESTART OR BURY FAILED PROCESS
  • 36. PROCESSES P1 P2 p1 = spawn(fn -> end) # > #PID<0.86.0> Process.alive?(p1) # > false p2 = self() # > #PID<0.95.0> Process.alive?(p2) # > true
  • 37. PROCESSES P1 P2 p1 = spawn(fn -> end) # > #PID<0.86.0> Process.alive?(p1) # > false p2 = self() # > #PID<0.95.0> Process.alive?(p2) # > true
  • 38. PROCESSES COMMUNICATION P1 P2 p1 = self() # > #PID<0.81.0> msg = "Ping" # > "Ping" p2 = spawn(fn -> end) # > Ping # > #PID<0.101.0> receive do msg -> IO.puts(msg) end # > Pong # > :ok IO.puts(msg) send(p1, "Pong")
  • 39. PROCESSES COMMUNICATION P1 P2 p1 = self() # > #PID<0.81.0> msg = "Ping" # > "Ping" p2 = spawn(fn -> end) # > Ping # > #PID<0.101.0> receive do msg -> IO.puts(msg) end # > Pong # > :ok IO.puts(msg) send(p1, "Pong")
  • 40. PROCESSES COMMUNICATION P1 P2 p1 = self() # > #PID<0.81.0> msg = "Ping" # > "Ping" p2 = spawn(fn -> end) # > Ping # > #PID<0.101.0> receive do msg -> IO.puts(msg) end # > Pong # > :ok MESSAGE IO.puts(msg) send(p1, "Pong")
  • 41. PROCESSES LINKING P1 P2 spawn_link(fn -> end) P1 P2p2 = spawn(fn -> end) # > #PID<0.113.0> Process.link(p2) # > true raise "Dad, I'm dead" # > ** (EXIT from #PID<0.81.0>) an exception was raised: # > ** (RuntimeError) Dad, I'm dead :timer.sleep(1000) raise "Mom, I'm dead” # > ** (EXIT from #PID<0.81.0>) an exception was raised: # > ** (RuntimeError) Mom, I'm dead # > :ok
  • 42. PROCESSES LINKING P1 P2 spawn_link(fn -> end) P1 P2p2 = spawn(fn -> end) # > #PID<0.113.0> Process.link(p2) # > true raise "Dad, I'm dead" # > ** (EXIT from #PID<0.81.0>) an exception was raised: # > ** (RuntimeError) Dad, I'm dead :timer.sleep(1000) raise "Mom, I'm dead” # > ** (EXIT from #PID<0.81.0>) an exception was raised: # > ** (RuntimeError) Mom, I'm dead # > :ok
  • 43. PROCESSES LINKING P1 P2 spawn_link(fn -> end) P1 P2p2 = spawn(fn -> end) # > #PID<0.113.0> Process.link(p2) # > true raise "Dad, I'm dead" # > ** (EXIT from #PID<0.81.0>) an exception was raised: # > ** (RuntimeError) Dad, I'm dead :timer.sleep(1000) raise "Mom, I'm dead” # > ** (EXIT from #PID<0.81.0>) an exception was raised: # > ** (RuntimeError) Mom, I'm dead # > :ok
  • 44. L L L L |> Application discovery |> Failure detection |> Processes management |> Hot code swapping |> Server structure OTP ERLANG MNESIA L L L L OTP+ + = A A
  • 45. L L L L |> Application discovery |> Failure detection |> Processes management |> Hot code swapping |> Server structure OTP ERLANG MNESIA L L L L OTP+ + = A A P P P
  • 46. |> Task (performs async work) |> Agent (holds state) |> GenServer (general purpose client-server scaffold) |> Supervisor OTHER CONCURRENT ABSTRACTIONS
  • 47. TASK defmodule Tea.Master do def brew do IO.puts "Brewing tea..." :timer.sleep(1000) IO.puts "Tea is ready!" "a cup of tea" end end IO.puts "[Tea Master] Please sit down and take a rest" IO.puts "[Tea Master] I need some time to brew the tea" worker = Task.async(fn -> Tea.Master.brew() end) IO.puts "[Guest] I have to clean my mind" result = Task.await(worker) IO.puts "The result is #{result}" # > [Tea Master] Please sit down and take a rest # > [Tea Master] I need some time to brew the tea # > [Guest] I have to clean my mind # > Brewing tea... # > Tea is ready! # > The result is a cup of tea
  • 48. AGENT { :ok, wisdom } = Agent.start(fn -> "Elixir" end) # > {:ok, #PID<0.83.0>} Agent.get(wisdom, &(&1)) # > "Elixir" Agent.update(wisdom, &(&1 <> "is awesome")) # > :ok Agent.get(wisdom, &(&1)) # > "Elixiris awesome" # > nil Agent.start(fn -> [] end, name: Fridge) # > {:ok, #PID<0.89.0>} Agent.update(Fridge, &(["milk" | &1])) # > :ok Agent.get(Fridge, &(&1)) # > ["milk"] Agent.update(Fridge, &(["butter" | &1])) # > :ok Agent.get(Fridge, &(&1)) # > ["butter", "milk"]
  • 49. GENSERVER defmodule Stack do use GenServer # Client API def start_link do GenServer.start_link(__MODULE__, :ok, []) end def push(pid, item) do GenServer.cast(pid, {:push, item}) end def pop(pid) do GenServer.call(pid, :pop) end # Server API def handle_call(:pop, _from, state) do [item | next_state] = state {:reply, item, next_state} end def handle_cast({:push, item}, state) do next_state = [item | state] {:noreply, next_state} end end {:ok, stack} = Stack.start_link # > {:ok, #PID<0.117.0>} Stack.push(stack, "milk") # > :ok Stack.push(stack, "butter") # > :ok Stack.pop(stack) # > "butter" Stack.pop(stack) # > "milk"
  • 50. SUPERVISOR defmodule Mathex do use Application # See http://elixir-lang.org/docs/stable/elixir/Application.html # for more information on OTP Applications def start(_type, _args) do import Supervisor.Spec # Define workers and child supervisors to be supervised children = [ supervisor(Mathex.Repo, []), supervisor(Mathex.Endpoint, []), # Start your own worker by calling: Mathex.Worker.start_link(arg1, arg2, arg3) # worker(Mathex.Worker, [arg1, arg2, arg3]), ] # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: Mathex.Supervisor] Supervisor.start_link(children, opts) end # Tell Phoenix to update the endpoint configuration # whenever the application is updated. def config_change(changed, _new, removed) do Mathex.Endpoint.config_change(changed, removed) :ok end end
  • 53. DOCUMENTATION |>First-class citizen |>h helper |>@docmodule |>@doc |>exdoc |>doctets |>README Driven Development defmodule YAC do @moduledoc """ Yet Another Calculator """ @doc """ Sum two numbers ## Examples iex> sum(1, 2) 3 """ def sum(a, b) do a + b end end
  • 54. |> https://learnxinyminutes.com/docs/elixir |> http://elixir-lang.org |> http://blog.plataformatec.com.br/2015/06/elixir-in-times- of-microservices |> http://howistart.org/posts/elixir/1 |> https://www.youtube.com/watch?v=L0qC97ytMjQ RESOURCES
  • 55. ?