我正在做这个练习来自 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.
这是我想出的:
-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]))).
这是它的输出:
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
如果我真的了解 Erlang,我会不会做不同的事情来改进这段代码?特别是:
最佳答案
欢迎来到二郎!我希望你和我一样喜欢它。
Is there any alternative to specifying a do-nothing "true" clause in the last two if statements?
你可以把这些关掉。我用这个运行了你的代码:
if NextCircuitNumber > 0 ->
NextNodeName ! NextCircuitNumber
end,
if CircuitNumber > 1 ->
node(NodeNumber, NumberOfNodes)
end
它对我有用。
Am I indeed terminating gracefully? Is any special action required when ending a process which was registered?
是的,你是。您可以通过运行
i().
来验证这一点。命令。这将显示进程列表,如果您注册的进程没有终止,您会看到许多已注册的进程遗留下来,如 node0
, node1
等。您也将无法再次运行您的程序,因为尝试注册已注册的名称时会出错。至于你可以做的其他事情来改进代码,没有太多,因为你的代码基本上没问题。我可能会做的一件事是不使用
NextNodeName
多变的。您可以直接发送消息到node_name(NextNodeNumber)
这有效。此外,您可能可以做更多的模式匹配来改进事情。例如,我在使用您的代码时所做的一项更改是通过传入最后一个节点的编号
(NumberOfNodes - 1)
来生成进程。 ,而不是通过 NumberOfNodes
.然后,我可以在我的 node/2
中进行模式匹配像这样的函数头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.
这让我清理了一些
case
和 if
您的 node
中的逻辑功能并使其更整洁。希望能帮到你,祝你好运。
关于concurrency - Erlang类(class)并发练习: Can my answer be improved?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5135229/