SlideShare uma empresa Scribd logo
1 de 55
Baixar para ler 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
?

Mais conteúdo relacionado

Mais procurados

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
 

Mais procurados (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
 

Semelhante a 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 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 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 typesLuis Goldster
 
Python language data types
Python language data typesPython language data types
Python language data typesHoang Nguyen
 
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
 

Semelhante a 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
 

Último

Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesKrzysztofKkol1
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogueitservices996
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jNeo4j
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesVictoriaMetrics
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfkalichargn70th171
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecturerahul_net
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxSasikiranMarri
 
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdfSteve Caron
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...kalichargn70th171
 
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonApplitools
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldRoberto Pérez Alcolea
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLionel Briand
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorTier1 app
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITmanoharjgpsolutions
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsJean Silva
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shardsChristopher Curtin
 

Último (20)

Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogue
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 Updates
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecture
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
 
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
[ CNCF Q1 2024 ] Intro to Continuous Profiling and Grafana Pyroscope.pdf
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
 
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and Repair
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryError
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh IT
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero results
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards
 

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. ?