2011-03-08 28 views
4

我最近認真學習Erlang編程的書,我有一個問題。 以下是Erlang的正確方法嗎?這是(爲簡潔起見(沒有退出消息),在基本驗證後刪除日誌記錄)解決ch4環問題的方法。進程在它們傳遞了消息的預定次數後退出;第一個進程等待最後一條消息到達並退出。新手問題 - 應該在編程erlang時使用ifs還是short函數?

除了風格和實質的一般批評,你能告訴我,如果寫這樣的特殊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. 

回答

7

我覺得你的風格很好,很簡潔!幹得好!

幾點意見(個人喜好的問題):

  • 開始環可以改寫爲:

    start_ring(M, N, Message) when M < N, N > 0, M > 0 -> 
        spawn(ring, run_ring, [M, N, Message, 0]). 
    

    如果使用不當,這將有function_clause錯誤崩潰。處理錯誤返回時有一個很好的習慣,如果用戶可以對錯誤做一些明智的事情,例如返回{error, Reason},否則就會崩潰。我認爲在這種情況下,碰撞是安全的,因爲任何其他輸入都會是程序中的一個錯誤。

  • run_ring/4 + loop_ring/4:我不喜歡在帶有幾個子句的函數之間使用換行符。這使得很難看到函數在哪裏開始和結束。這些註釋可以放在子句體內而不是外部。它變得更加容易,現在識別功能標題(和看到的功能作爲一個單元):

    run_ring(M, 1, Message, Pid) when is_pid(Pid) -> 
        % last process that connects the ring 
        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 - special case for one 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代替(使用他們的第一條爲好,它的獎金文檔!)

3

按照Erlang best practices,應避免ifcase嵌套的兩倍以上:

嵌套代碼是包含 的案例/如果/在 其他案例/ if/receive語句中接收語句。它 是不好的編程風格寫 深層嵌套代碼 - 代碼有 傾向於漂移整個頁面到 的權利,並很快變得不可讀。 儘量將大部分代碼限制爲 最多兩個縮進級別。 這可以通過將 代碼分成更短的函數來實現。

除此之外,我想這是一個味道使用if/case或簡單模式匹配的問題。就個人而言,我更喜歡使用模式匹配而不是if或case。所以,如果你問我,你就以正確的方式做。

關於ifcase,通常你可以在前改寫成後者。有人說:

「總是使用案例,如果構造 有點破」。

好了,兩種構建工作非常不同。在if結構計算的表達式是一個後衛​​,它有很多的限制 - 由於這一事實,你不能有副作用進入看守,被拍攝無關的分支評估 - 。案例構造沒有這個「限制」。您可以使用沒有任何表情,其結果將形成對抗的情況下的模式相匹配。

可能重複:

Erlang style - case vs function pattern matching

相關問題