我最近开始认真学习Erlang编程一书,我有一个问题。下面是Erlang的正确方法吗?这是ch4对环问题的解决方案(为简洁起见(无退出消息),在基本验证后删除了日志)。进程在传递预期次数的消息后退出;第一个进程等待最后一条消息到达它,然后退出。
除了对风格和实质的一般性批评之外,你能告诉我像这样编写特殊的1-2行函数是否是正确的风格,或者是否应该使用if-s,cases s等?
start_ring( 0, _, _ ) -> {error, badarg};
start_ring( _, 0, _ ) -> {error, badarg};
start_ring( M, N, Message ) ->
spawn( ring, run_ring, [M, N, Message, 0] ).
% last process that connects the ring
run_ring( M, 1, Message, Pid ) when is_pid(Pid) ->
loop_ring( M, Message, Pid, false );
% process in the middle
run_ring( M, N, Message, Pid ) when is_pid(Pid) ->
loop_ring( M, Message, spawn( ring, run_ring, [M, N-1, Message, Pid] ), false );
% first process - special case for one process
run_ring( M, 1, Message, _ ) ->
loop_ring( M, self() ! Message, self(), true );
% first process
run_ring( M, N, Message, _ ) ->
NextPid = spawn( ring, run_ring, [M, N-1, Message, self()] ),
loop_ring( M, NextPid ! Message, NextPid, true ).
loop_ring( 0, _, _, _ ) -> ok;
loop_ring( 1, Message, Next, true ) -> ok;
loop_ring( M, Message, Next, IsMaster ) ->
receive
Message -> loop_ring( M - 1, Next ! Message, Next, IsMaster )
end.发布于 2011-03-08 17:29:52
我觉得你的风格很好,很简洁!干得好!
一些评论(个人喜好的问题):
当M< N,N> 0,M>0时start_ring( M,N,Message )产生( ->,run_ring,M,N,Message,0)。
如果使用不当,它将崩溃并出现function_clause错误。在处理错误返回时有一个很好的习惯,如果用户可以对错误做一些合理的处理,例如返回{error, Reason},否则就会崩溃。我认为在这种情况下,直接崩溃是安全的,因为任何其他输入都将是program.
run_ring/4 +loop_ring/4中的错误:我不喜欢在包含多个子句的函数之间使用换行符。这使得看清函数的开始和结束变得更加困难。然后可以将注释放在子句主体内,而不是放在子句主体之外。现在识别函数头变得更容易了(并将函数看作一个单元):run_ring(M,1,Message,Pid) when is_pid(Pid) -> %最后一个连接环的进程loop_ring(M,Message,Pid,false);run_ring(M,N,Message,Pid) when is_pid(Pid) -> % process in the middle loop_ring(M,Message,spawn( ring,run_ring,M,N-1,Message,Pid),false);run_ring(M,1,Message,_) -> % first process -一个进程的特例loop_ring(M,self()!Message,self(),true);run_ring(M,N,Message,_) -> % first process NextPid = spawn(ring,run_ring,M,N-1,Message,self()),loop_ring(M,NextPid!Message,NextPid,true)。
spawn_link/3而不是spawn/3,除非您知道自己不需要它。当你开发你的程序时,它使得检测错误等变得容易得多。
loop_ring/4的第二个子句发出编译器警告。改为使用_Message和_Next (也可以在第一个子句中使用它们,它是bonus documentation!)发布于 2011-03-08 21:06:23
根据Erlang best practices,人们应该避免if和case嵌套两次以上:
嵌套代码是在其他case/if/receive语句中包含case/if/receive语句的代码。编写深度嵌套的代码是糟糕的编程风格-代码有向右漂移的趋势,很快就会变得不可读。尽量将大部分代码限制在最多两级缩进。这可以通过将代码划分为更短的函数来实现。
除此之外,我认为使用if/case或简单的模式匹配只是一个品味问题。就我个人而言,我更喜欢使用模式匹配,而不是if或case。所以,如果你问我,你的做法是对的。
关于if和case,通常您可以将前者重写为后者。有人说:
“总是使用大小写,if结构有点问题”。
嗯,这两个结构的工作方式非常不同。在if构造中计算的表达式是一个guard,它有很多限制- -因为你不能对guard有副作用,它的计算与-的分支无关。case构造没有这个“限制”。您可以在其中使用任何表达式,其结果将与构成案例的模式进行匹配。
可能的重复项:
https://stackoverflow.com/questions/5229997
复制相似问题