Erlang课程并发练习:我的答案能否改善? [英] Erlang course concurrency exercise: Can my answer be improved?

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

问题描述

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


2)编写一个启动N
进程的函数,并发送
消息M次
进程在环。在
消息发送后,进程
应该正常终止。


这是我刚刚出现的与:

  -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) - >
列表:foreach(fun(NodeNumber) - >
register(node_name(NodeNumber))
spawn(ring,node,[NodeNumber,NumberOfNodes]))
end,
列表:seq(0,NumberOfNodes - 1)),
node_name(0)! NumberOfCircuits,
好​​的。

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

这是它的输出:

  17>戒指:开始(3,2)。 
节点0电路2
ok
节点1电路2
节点2电路2
节点0电路1
节点1电路1
节点2电路1

如果我真的知道Erlang,我可以用不同的方式改进这段代码吗?具体来说:




  • 在最后两个if语句中是否有任何替代方法指定do-nothingtrue子句? / p>


  • 我确实终止了在结束注册过程中是否需要特殊的操作?



解决方案

欢迎来到Erlang!我希望你尽可能多地喜欢它。


有没有任何替代方法来指定最后一个do-nothingtrue子句两个if语句?


你可以把它们关掉。我运行了你的代码:

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

它为我工作。


我确实终止了优雅吗?在结束注册过程中是否需要特别的操作?


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



至于您可以做的其他改进代码,没有太多,因为您的代码基本上是正常的。我可以做的一件事是离开 NextNodeName 变量。您可以直接向 node_name(NextNodeNumber)发送消息。



此外,您可能会更多的模式匹配来改善事物。例如,我在玩你的代码时所做的一个改变是通过传递最后一个节点(NumberOfNodes - 1)的数量来产生进程,而不是传递 NumberOfNodes 。然后,我可以在我的 node / 2 函数头文件中模式匹配这样

  node(LastNode,LastNode) - > 
%对最后一个节点进行特定操作,例如将消息传递回node0
%,并减少CircuitNumber
节点(NodeNumber,LastNode) - >
%为每个其他节点做事情。

这允许我清理一些案例如果节点中的逻辑函数,并使其全部有点整齐。



希望有所帮助,祝你好运。


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天全站免登陆