Last active
October 30, 2017 14:12
-
-
Save uri/93f95ab98c8cb605122e3815b67863c1 to your computer and use it in GitHub Desktop.
Two implementations of a stack in Elixir; one using GenServer and the other with send, receive, and pids.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule StackGenServer do | |
use GenServer | |
def start, do: GenServer.start(__MODULE__, [], name: __MODULE__) | |
def query, do: GenServer.call(__MODULE__, :query) | |
def pop, do: GenServer.call(__MODULE__, :pop) | |
def push(element), do: GenServer.call(__MODULE__, { :push, element }) | |
def handle_call(:query, _from, stack), do: {:reply, stack, stack} | |
def handle_call(:pop, _from, [h|t]), do: {:reply, h, t} | |
def handle_call(:pop, _from, []), do: {:reply, nil, []} | |
def handle_call({ :push, element }, _from, stack), do: {:reply, [element | stack], [element | stack]} | |
end | |
defmodule StackPid do | |
def start state do | |
spawn fn -> | |
handle state | |
end | |
end | |
def query pid do | |
send pid, { :query, self } | |
receive do | |
{:reply, stack} -> stack | |
end | |
end | |
def push pid, element do | |
send pid, { {:push, element}, self } | |
receive do | |
{:reply, current_stack} -> current_stack | |
end | |
end | |
def pop pid do | |
send pid, { :pop, self } | |
receive do | |
{:reply, element} -> element | |
{:error, _msg} -> nil | |
end | |
end | |
defp handle current_state do | |
receive do | |
{ {:push, element}, from } -> reply_push element, from, current_state | |
{ :pop, from } -> | |
if current_state == [] do | |
send from, {:error, "Stack is empty."} | |
handle [] | |
else | |
reply_pop from, current_state | |
end | |
{ :query, from } -> reply_query from, current_state | |
end | |
end | |
defp reply_query from, current_state do | |
send from, {:reply, current_state } | |
handle current_state | |
end | |
defp reply_pop from, [h|t] do | |
send from, {:reply, h} | |
handle t | |
end | |
defp reply_push element, from, current_state do | |
new_state = [ element | current_state ] | |
send from, {:reply, new_state} | |
handle new_state | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment