Manuel Albarran

A random notes about Elixir

GenServer reverse - reverse engineering

12 Feb 2017 » elixir, GenServer
s = spawn(fn -> receive do m -> IO.inspect m end end) 
GenServer.cast(s, {:a})     
#> {:"$gen_cast", {:a}}

s = spawn(fn -> receive do m -> IO.inspect m end end) 
GenServer.call(s, {:a}) 
# :gen.call(s, :"$gen_call", {:a}, 5_000)
# :gen_server.call(s, {:a})
#> {:"$gen_call", {#PID<0.80.0>, #Reference<0.0.4.127>}, {:a}}

defmodule M do
  use GenServer
  def handle_call(_action, _from, state), do: {:reply, :response, state}
end

{:ok, s} = GenServer.start_link(M, :ok, [])
ref = make_ref
#> #Reference<0.0.3.14>

send(s, {:"$gen_call", {self, ref}, {:a}})
Process.info(self, :messages)
#> {:messages, [{#Reference<0.0.3.14>, :response}]}
receive do
  {ref, value} -> IO.inspect value 
end
#> :response

pingpong = spawn(fn -> receive do 
  {:"$gen_call", {pid, ref}, :ping} -> send pid, {ref, :pong}
end end) 

GenServer.call(pingpong, :ping)
#> :pong


y0 = fn f -> (fn -> (fn z -> z.(z) end).(fn x -> f.(fn -> (x.(x)).() end) end) end) end

infinite_pingpong = spawn(y0.(fn f ->
  receive do 
    {:"$gen_call", {pid, ref}, :ping} -> send pid, {ref, :pong} 
    {:"$gen_cast", :ping} -> IO.puts :pong
  end
  f.()
end)
)

GenServer.call(infinite_pingpong, :ping)
#> :pong

GenServer.cast(infinite_pingpong, :ping)
#> pong
#> :ok


pid = spawn(fn -> 
  receive do 2 -> IO.puts 2 end
  receive do 1 -> IO.puts 1 end
end)

send(pid, 1)
send(pid, 2)
#> 2
#> 1