Using catch and receive together (like in erlang)

How this piece of code would look like in elixir? I haven’t seen catch and receive being used together yet …

active_connections(SupPid) ->
	Tag = erlang:monitor(process, SupPid),
	catch erlang:send(SupPid, {?MODULE, active_connections, self(), Tag},
		[noconnect]),
	receive
		{Tag, Ret} ->
			erlang:demonitor(Tag, [flush]),
			Ret;
		{'DOWN', Tag, _, _, noconnection} ->
			exit({nodedown, node(SupPid)});
		{'DOWN', Tag, _, _, Reason} ->
			exit(Reason)
	after 5000 ->
		erlang:demonitor(Tag, [flush]),
		exit(timeout)
	end.
1 Like
def active_connections(sup_pid) do
  tag = Process.monitor(sup_pid, :process)
  
  try do
    Process.send(sup_pid, {__MODULE__, :active_connections, self(), tag}, [:noconnect])
  catch # ???
  end
  
  receive do
    {^tag, ret} ->
      Process.demonitor(tag, [:flush])
      ret
    {:DOWN, ^tag, _, _, :noconnection} ->
      exit({:nodedown, node(sup_pid)})
    {:DOWN, ^tag, _, _, reason} ->
      exit(reason)
  after
    5000 ->
      Process.demonitor(tag, [:flush])
      exit(:timeout)
  end
end

But what to do with catch?

Then there is also this piece

try Protocol:start_link(Ref, Socket, Transport, Opts) of
  {ok, Pid} ->
    shoot(State, CurConns, NbChildren, Sleepers, To, Socket, Pid, Pid);
  {ok, SupPid, ProtocolPid} when ConnType =:= supervisor ->
    shoot(State, CurConns, NbChildren, Sleepers, To, Socket, SupPid, ProtocolPid);
  Ret ->
    To ! self(),
    error_logger:error_msg(
      "Ranch listener ~p connection process start failure; "
      "~p:start_link/4 returned: ~999999p~n",
      [Ref, Protocol, Ret]),
    Transport:close(Socket),
    loop(State, CurConns, NbChildren, Sleepers)
catch Class:Reason ->
  To ! self(),
  error_logger:error_msg(
    "Ranch listener ~p connection process start failure; "
    "~p:start_link/4 crashed with reason: ~p:~999999p~n",
    [Ref, Protocol, Class, Reason]),
  loop(State, CurConns, NbChildren, Sleepers)
end;

How does that translate to elixir’s try do/catch?

Elixir does not feature the catch operator as it’s regarded as a construct that is generally error prone (swallowing all the errors).

An Elixir’s equivalent to Erlang’s catch operator would be something like this:

try do
  expr
catch
  kind, reason -> {kind, reason}
end
1 Like

Thank you!

And how would this translate into elixir?

try mod:func() of
  {ok, Pid} ->
    shoot(State, CurConns, NbChildren, Sleepers, To, Socket, Pid, Pid);
  {ok, SupPid, ProtocolPid} when ConnType =:= supervisor ->
    shoot(State, CurConns, NbChildren, Sleepers, To, Socket, SupPid, ProtocolPid);
  ...
catch Class:Reason ->
  ...
end;

Would it be

try do
  Mod.func()
catch
  class, reason ->
    ...
else
  {:ok, pid} ->
    shoot(state, cur_conns, nb_children, sleepers, to, socket, pid, pid)
  {:ok, sup_pid, protocol_pid} when conn_type === :supervisor ->
    shoot(state, cur_conns, nb_children, sleepers, to, socket, sup_pid, protocol_pid)
  ...
end

?

Yes, exactly.