Skip to content

Instantly share code, notes, and snippets.

@nubunto
Created September 24, 2018 19:04
Show Gist options
  • Save nubunto/4bc490d1c6368032a995f31e0603944a to your computer and use it in GitHub Desktop.
Save nubunto/4bc490d1c6368032a995f31e0603944a to your computer and use it in GitHub Desktop.
Elixir Portal Application: http://howistart.org
defmodule Portal.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
def start(_type, _args) do
# List all child processes to be supervised
children = [
# Starts a worker by calling: Portal.Worker.start_link(arg)
# {Portal.Worker, arg},
Portal.Door
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :simple_one_for_one, name: Portal.Supervisor]
Supervisor.start_link(children, opts)
end
end
defmodule Portal.Door do
def child_spec(opts) do
IO.inspect opts
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [opts]},
type: :worker
}
end
def start_link(color) do
IO.inspect(color)
Agent.start_link(fn -> [] end, name: color)
end
def get(door) do
Agent.get(door, fn state -> state end)
end
def push(door, data) do
Agent.update(door, fn state -> [data | state] end)
end
def pop(door) do
Agent.get_and_update(door, fn
[] -> {{:error, :empty}, []}
[ value | tail] -> {{:ok, value}, tail}
end)
end
end
defmodule Portal do
defstruct left: nil, right: nil
def shoot(color) do
Supervisor.start_child(Portal.Supervisor, [color])
end
def transfer(left, right, data) do
for item <- data do
Portal.Door.push(left, item)
end
%Portal{left: left, right: right}
end
def push_right(%Portal{left: left, right: right} = portal) do
case Portal.Door.pop(left) do
{:error, :empty} -> :ok
{:ok, value} -> Portal.Door.push(right, value)
end
portal
end
end
defimpl Inspect, for: Portal do
def inspect(%Portal{left: left, right: right}, _) do
left_door = inspect(left)
right_door = inspect(right)
left_data = inspect(Enum.reverse(Portal.Door.get(left)))
right_data = inspect(Portal.Door.get(right))
max = max(String.length(left_door), String.length(left_data))
"""
#Portal<
#{String.pad_leading(left_door, max)} <=> #{right_door}
#{String.pad_leading(left_data, max)} <=> #{right_data}
>
"""
end
end
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [hipe]
Interactive Elixir (1.7.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Portal.shoot :orange
** (exit) exited in: GenServer.call(Portal.Supervisor, {:start_child, [:orange]}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(elixir) lib/gen_server.ex:914: GenServer.call/3
defmodule Portal.Supervisor do
use Supervisor
def start_link(opts) do
Supervisor.start_link(__MODULE__, :ok, opts)
end
def init(_arg) do
children = [
Portal.Door
]
Supervisor.init(children, strategy: :simple_one_for_one)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment