Scenic City Summit Elixir OTP
import IEx.Helpers
Scenic City course
1 + 1
input = 42
input + 1
-
(c)onstruct
-
(r)educe?
-
(c) ?
defmodule Acc do
def new(s) when is_bitstring(s) do
String.to_integer(s)
end
def new(int) when is_integer(int) do
int
end
def add(acc, i) when is_integer(i) do
acc + i
end
def inc(acc) do
add(acc, 1)
end
def dec(acc) do
add(acc, -1)
end
def show(acc) do
"The ants arr is #{acc}"
end
end
import Acc
two_steps_forward_and_one_back =
input
|> new()
|> inc()
|> inc()
|> dec()
|> show()
list = [1, 1, -1]
input = 42
Enum.reduce(list, input, &Acc.add/2)
Build a counting service
defmodule Service do
def start(input) do
count = input |> Acc.new()
spawn(fn -> loop(count) end)
end
def inc(pid) do
send(pid, :inc)
end
def dec(pid) do
send(pid, :dec)
end
def show(pid) do
send(pid, {:show, self()})
receive do
m -> m
end
end
def loop(count) do
count
|> listen()
|> loop()
end
def listen(count) do
receive do
:inc ->
Acc.inc(count)
:dec ->
Acc.dec(count)
{:show, from_pid } ->
# send back the count to the user
message = Acc.show(count)
send(from_pid, message)
# return the current count so our recursion doesn't blow up
count
end
end
end
livebook =
self()
Process.info(livebook)
count = 12
message = :dec
send(livebook, message)
Service.listen(count)
count = 11
message = {:show, self()}
send(self(), message)
Service.listen(count)
receive do
m -> m
end
service = Service.start(input)
Process.alive?(service)
send(service, {:show, self()})
send(service, :inc)
send(service, {:show, self()})
receive do
m -> m
end
Service.show(service)
OTP GenServer
defmodule Server do
use GenServer
# client
def start_link(input) do
GenServer.start_link(Server, input)
end
def inc(pid) do
GenServer.cast(pid, :inc)
end
def dec(pid) do
GenServer.cast(pid, :dec)
end
def show(pid) do
GenServer.call(pid, :show)
end
# api stuff will all go here
# server
# construct
@impl true
def init(input) do
initial_state = Acc.new(input)
{:ok, initial_state}
end
# reduce
@impl true
def handle_cast(:inc, count) do
new_state = Acc.inc(count)
{:noreply, new_state}
end
@impl true
def handle_cast(:dec, count) do
new_state = Acc.dec(count)
{:noreply, new_state}
end
# convert
@impl true
def handle_call(:show, _from_pid, count) do
message = Acc.show(count)
{:reply, message, count}
end
end
{:ok, pid} = Server.start_link(input)
GenServer.cast(pid, :inc)
GenServer.cast(pid, :inc)
GenServer.cast(pid, :inc)
GenServer.call(pid, :show)
Server.inc(pid)
Server.inc(pid)
Server.inc(pid)
Server.inc(pid)
Server.inc(pid)
Server.show(pid)
:sys.get_state(pid)
h GenServer
OTP Lifecycle (supervision)