如何将这段丹药代码转换为Erlang?

zaqlnxep  于 2022-12-08  发布在  Erlang
关注(0)|答案(1)|浏览(171)

在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中的工作方式不同,我尝试将其更改为该格式,但在酏剂代码中存在的一些功能在Erlang中很难显示。

j5fpnvbx

j5fpnvbx1#

首先,直接翻译...

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代码相同的目的。

相关问题