Erlang课程并发练习:我的答案可以改进吗? [英] Erlang course concurrency exercise: Can my answer be improved?

查看:87
本文介绍了Erlang课程并发练习:我的答案可以改进吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 erlang.org课程进行此练习:


2)编写一个函数,它在一个循环中启动N
个进程,并在所有
进程中发送一个
消息M次在环中。在
消息发送后,进程
应该正常结束。


与:

  -module(ring)。 
-export([start / 2,node / 2])。

节点(NodeNumber,NumberOfNodes) - >
NextNodeNumber =(NodeNumber + 1)rem NumberOfNodes,
NextNodeName = node_name(NextNodeNumber),
receive
CircuitNumber - >
io:format(Node〜p Circuit〜p〜n,[NodeNumber,CircuitNumber]),
LastNode = NodeNumber =:= NumberOfNodes - 1,
NextCircuitNumber = case LastNode of
true - >
CircuitNumber - 1;
false - >
CircuitNumber
end,
if
NextCircuitNumber> 0 - >
NextNodeName! NextCircuitNumber;
true - >
ok
end,
如果
CircuitNumber> 1 - >
node(NodeNumber,NumberOfNodes);
true - >
ok
end
end。

start(NumberOfNodes,NumberOfCircuits) - >
list:foreach(fun(NodeNumber) - >
register(node_name(NodeNumber),
spawn(ring,node,[NodeNumber,NumberOfNodes]))
end,
列表:seq(0,NumberOfNodes - 1)),
node_name(0)! NumberOfCircuits,
ok。

node_name(NodeNumber) - >
list_to_atom(lists:flatten(io_lib:format(node〜w,[NodeNumber])))。

以下是其输出:

  17> ring:start(3,2)。 
节点0电路2
ok
节点1电路2
节点2电路2
节点0电路1
节点1电路1
节点2 Circuit 1



如果我实际上知道Erlang,我可以不同的方法来改进这个代码?具体来说:




  • 在最后两个if语句中指定一个do-nothing的true / p>


  • 我真的会顺利结束吗?在结束已注册的进程时是否需要执行任何特殊操作?



解决方案

欢迎来到Erlang!


有没有其他方法可以在最后一个指定一个do-nothing的true子句两个if语句?


您可以将它们关闭。我用你的代码:

 如果NextCircuitNumber> 0  - > 
NextNodeName! NextCircuitNumber
end,
如果CircuitNumber> 1 - >
节点(NodeNumber,NumberOfNodes)
end


我真的终止了吗?在结束已注册的进程时是否需要执行任何特殊操作?


是的。您可以通过运行 i()。命令来验证这一点。这将显示进程列表,如果你注册的进程没有终止,你会看到很多你注册的进程,如 node0 node1 等。您也不能再次运行您的程序,因为尝试注册已经注册的名称时会出错。



至于其他方面你可以做的改进代码,没有太多,因为你的代码基本上是罚款。我可以做的一件事是留下 NextNodeName 变量。你可以直接发送一个消息到 node_name(NextNodeNumber),并且可以工作。



有点更多的模式匹配改善的东西。例如,我在使用你的代码时做的一个改变是通过传递最后一个节点的数目(NumberOfNodes - 1)来产生进程,而不是传递 NumberOfNodes 。然后,我可以在我的 node / 2 函数头中进行模式匹配

  node(LastNode,LastNode) - > 
%执行特定于最后一个节点的事情,例如将消息传回节点0
%并减少CircuitNumber
节点(节点号,上一节点) - >
%为每个其他节点执行操作。

这允许我清理一些案例节点函数中的 if 逻辑,并使它有点整齐。



希望有帮助,祝你好运。


I am doing this exercise from the erlang.org course:

2) Write a function which starts N processes in a ring, and sends a message M times around all the processes in the ring. After the messages have been sent the processes should terminate gracefully.

Here's what I've come up with:

-module(ring).
-export([start/2, node/2]).

node(NodeNumber, NumberOfNodes) ->
  NextNodeNumber = (NodeNumber + 1) rem NumberOfNodes,
  NextNodeName = node_name(NextNodeNumber),
  receive
    CircuitNumber ->
      io:format("Node ~p Circuit ~p~n", [NodeNumber, CircuitNumber]),
      LastNode = NodeNumber =:= NumberOfNodes - 1,
      NextCircuitNumber = case LastNode of
                           true ->
                             CircuitNumber - 1;
                           false ->
                             CircuitNumber
                         end,
      if
        NextCircuitNumber > 0 ->
          NextNodeName ! NextCircuitNumber;
        true ->
          ok
      end,
      if
        CircuitNumber > 1 ->
          node(NodeNumber, NumberOfNodes);
        true ->
          ok
      end
  end.

start(NumberOfNodes, NumberOfCircuits) ->
  lists:foreach(fun(NodeNumber) ->
                    register(node_name(NodeNumber),
                             spawn(ring, node, [NodeNumber, NumberOfNodes]))
                end,
                lists:seq(0, NumberOfNodes - 1)),
  node_name(0) ! NumberOfCircuits,
  ok.

node_name(NodeNumber) ->
  list_to_atom(lists:flatten(io_lib:format("node~w", [NodeNumber]))).

Here is its output:

17> ring:start(3, 2).
Node 0 Circuit 2
ok
Node 1 Circuit 2
Node 2 Circuit 2
Node 0 Circuit 1
Node 1 Circuit 1
Node 2 Circuit 1

If I actually knew Erlang, would could I do differently to improve this code? And specifically:

  • Is there any alternative to specifying a do-nothing "true" clause in the last two if statements?

  • Am I indeed terminating gracefully? Is any special action required when ending a process which was registered?

解决方案

Welcome to Erlang! I hope you enjoy it as much as I do.

Is there any alternative to specifying a do-nothing "true" clause in the last two if statements?

You can just leave these off. I ran your code with this:

if NextCircuitNumber > 0 ->
  NextNodeName ! NextCircuitNumber
end,
if CircuitNumber > 1 ->
  node(NodeNumber, NumberOfNodes)
end

and it worked for me.

Am I indeed terminating gracefully? Is any special action required when ending a process which was registered?

Yes you are. You can verify this by running the i(). command. This will show you the list of processes, and if your registered processes weren't terminating, you would see alot of your registered processes left over like node0, node1, etc. You also would not be able to run your program a second time, because it would error trying to register an already registered name.

As far as other things you could do to improve the code, there is not much because your code is basically fine. One thing I might do is leave off the NextNodeName variable. You can just send a message directly to node_name(NextNodeNumber) and that works.

Also, you could probably do a bit more pattern matching to improve things. For example, one change I made while playing with your code was to spawn the processes by passing in the number of the last node (NumberOfNodes - 1), rather than passing the NumberOfNodes. Then, I could pattern match in my node/2 function header like this

node(LastNode, LastNode) ->
    % Do things specific to the last node, like passing message back to node0
    % and decrementing the CircuitNumber
node(NodeNumber, LastNode) ->
    % Do things for every other node.

That allowed me to clean up some of the case and if logic in your node function and make it all a little tidier.

Hope that helps, and good luck.

这篇关于Erlang课程并发练习:我的答案可以改进吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆