如何将这段万能代码转换为Erlang?



elixir中有一段代码检查节点是否活着,并在此基础上进行一些操作。如何在erlang中实现相同的功能?

def make_distributed([head | tail],l) do
unless Node.alive?() do
try do
{ip_tuple,_,_} = head
current_ip = to_string(:inet_parse.ntoa(ip_tuple))
if current_ip === "127.0.0.1" do
if l > 1 do
make_distributed(tail,l-1)
else 
IO.puts "Could not make current node distributed."
end
else
server_node_name = String.to_atom("client@" <> current_ip)
Node.start(server_node_name)
Node.set_cookie(server_node_name,:monster)
Node.connect(String.to_atom("server@" <> current_ip))
end
rescue
_ -> if l > 1, do: make_distributed(tail,l-1), else: IO.puts "Could not make current node distributed."
end
end
end

如果……else在erlang中的工作方式不同,我尝试将其更改为那种格式,但elixir代码中的一些功能很难在erlang中显示。

首先,直接翻译…

make_distributed([Head | Tail], L) ->
case node:is_alive() of
false ->
false; % Not sure what unless returns if the condition is false
true ->
try
{IPTuple, _, _} = Head,
CurrentIP = iolist_to_binary(inet_parse:ntoa(IPTuple)),
case CurrentIP of
<<"127.0.0.1">> ->
case L of
L when L > 1 ->
make_distributed(Tail, L - 1);
_ ->
io:format("Could not make current node distributed.")
end;
_ ->
ServerNodeName = binary_to_atom(<<"client@", CurrentIP/binary>>),
net_kernel:start([ServerNodeName, longnames, 15000]),
erlang:set_cookie(ServerNodeName, monster),
net_kernel:connect_node(binary_to_atom(<<"server@", CurrentIP/binary>>))
end
catch
_:_ ->
case L of
L when L > 1 ->
make_distributed(Tail, L - 1);
_ ->
io:format("Could not make current node distributed.")
end
end
end.

但是那是一些非常丑陋的代码。让我们更有效地使用模式匹配…

make_distributed([{IPTuple, _, _} | Tail], L) ->
case node:is_alive() of
false ->
false; % Not sure what unless returns if the condition is false
true ->
try
case iolist_to_binary(inet_parse:ntoa(IPTuple)) of
<<"127.0.0.1">> when L > 1 ->
make_distributed(Tail, L - 1);
<<"127.0.0.1">> ->
io:format("Could not make current node distributed.");
CurrentIP ->
ServerNodeName = binary_to_atom(<<"client@", CurrentIP/binary>>),
net_kernel:start([ServerNodeName, longnames, 15000]),
erlang:set_cookie(ServerNodeName, monster),
net_kernel:connect_node(binary_to_atom(<<"server@", CurrentIP/binary>>))
end
catch
_:_ when L > 1 ->
make_distributed(Tail, L - 1);
_:_ ->
io:format("Could not make current node distributed.")
end
end.

我们不需要在每个递归步骤都检查节点的活跃度,对吧?

maybe_make_distributed(IPTuples, L) ->
case node:is_alive() of
false ->
false; % Not sure what unless returns if the condition is false
true ->
make_distributed(IPTuples, L)
end.
make_distributed([{IPTuple, _, _} | Tail], L) ->
try
case iolist_to_binary(inet_parse:ntoa(IPTuple)) of
<<"127.0.0.1">> when L > 1 ->
make_distributed(Tail, L - 1);
<<"127.0.0.1">> ->
io:format("Could not make current node distributed.");
CurrentIP ->
ServerNodeName = binary_to_atom(<<"client@", CurrentIP/binary>>),
net_kernel:start([ServerNodeName, longnames, 15000]),
erlang:set_cookie(ServerNodeName, monster),
net_kernel:connect_node(binary_to_atom(<<"server@", CurrentIP/binary>>))
end
catch
_:_ when L > 1 ->
make_distributed(Tail, L - 1);
_:_ ->
io:format("Could not make current node distributed.")
end.

最后,让我们将L > 1检查移到它自己的子句中,就像一个普通的递归函数…

maybe_make_distributed(IPTuples, L) ->
case node:is_alive() of
false ->
false; % Not sure what unless returns if the condition is false
true ->
make_distributed(IPTuples, L)
end.
make_distributed(_, 0) ->
io:format("Could not make current node distributed.");
make_distributed([{IPTuple, _, _} | Tail], L) ->
try
case iolist_to_binary(inet_parse:ntoa(IPTuple)) of
<<"127.0.0.1">> ->
make_distributed(Tail, L - 1);
CurrentIP ->
ServerNodeName = binary_to_atom(<<"client@", CurrentIP/binary>>),
net_kernel:start([ServerNodeName, longnames, 15000]),
erlang:set_cookie(ServerNodeName, monster),
net_kernel:connect_node(binary_to_atom(<<"server@", CurrentIP/binary>>))
end
catch
_:_ ->
make_distributed(Tail, L - 1)
end.

这就是我要在Erlang中编写的代码,以实现与Elixir代码相同的目标。

最新更新