2010-06-24 83 views
1

我在這裏有一個Erlang代碼片段,我想將它用於更慣用的Erlang,而不是粗略的Python翻譯。Erlang語法幫助

過程需要一對全等列表並將它們組合在一起。一些元素需要根據其屬性從一個列表或另一個列表中取出,而其餘元素需要進行總結。它工作正常,但我覺得它不是慣用的...

Process = fun([RockA, FishA, TreeA, BarkA, DogA, CowA, MooA, MilkA, CheeseA, BreadA, WineA, GrapesA], [RockB, FishB, TreeB, BarkB, DogB, CowB, MooB, MilkB, CheeseB, BreadB, WineB, GrapesB]) -> 
        if 
         RockA /= [0,0,0] -> 
          NewRock = RockA, 
          NewFish = FishA, 
          NewTree = TreeA, 
          NewBark = BarkA, 
          NewDog = DogA; 
         true -> 
          NewRock = RockB, 
          NewFish = FishB, 
          NewTree = TreeB, 
          NewBark = BarkB, 
          NewDog = DogB 
        end, 
        if 
         CowA > CowB -> 
          NewCow = CowA; 
         true -> 
          NewCow = CowB 
        end, 
        NewMoo = MooA + MooB, 
        NewMilk = MilkA + MilkB, 
        NewCheese = CheeseA + CheeseB, 
        NewBread = BreadA + BreadB, 
        NewWine = WineA + WineB, 
        NewGrapes = GrapesA + GrapesB, 
        [NewRock, NewFish, NewTree, NewBark, NewDog, NewMoo, NewMilk, NewCheese, NewBread, NewWine, NewGrapes]; 
      (_,_) -> 
        ok 
      end. 

回答

1

這裏有一些建議。但是,不管你喜歡中間變量賦值,這都是一個品味問題。請注意'case'和'if'是總是評估某些事物的表達式。我也刪除了「(,) - >確定」catch all;這似乎是在Erlang氣餒的防禦性編程。

Process = fun([RockA, FishA, TreeA, BarkA, DogA, CowA, MooA, MilkA, CheeseA, BreadA, WineA, GrapesA], 
       [RockB, FishB, TreeB, BarkB, DogB, CowB, MooB, MilkB, CheeseB, BreadB, WineB, GrapesB]) -> 

      FirstStuff = case RockA of 
          [ 0,0,0] -> 
          [RockB, FishB, TreeB, BarkB, DogB]; 
          _ -> 
          [RockA, FishA, TreeA, BarkA, DogA] 
         end, 

       NewCow = if 
         CowA > CowB -> 
          CowA; 
         true -> 
          CowB 
         end, 

       lists:flatten([ FirstStuff, 
           NewCow, 
           MooA + MooB, 
           MilkA + MilkB, 
           CheeseA + CheeseB, 
           BreadA + BreadB, 
           WineA + WineB, 
           GrapesA + GrapesB ]); 
      end. 

甚至......

Process = fun([RockA, FishA, TreeA, BarkA, DogA, CowA, MooA, MilkA, CheeseA, BreadA, WineA, GrapesA], 
       [RockB, FishB, TreeB, BarkB, DogB, CowB, MooB, MilkB, CheeseB, BreadB, WineB, GrapesB]) -> 

       lists:flatten([ case RockA of 
           [ 0,0,0] -> 
            [RockB, FishB, TreeB, BarkB, DogB]; 
           _ -> 
            [RockA, FishA, TreeA, BarkA, DogA] 
           end, 
           lists:max([CowA,CowB]), 
           MooA + MooB, 
           MilkA + MilkB, 
           CheeseA + CheeseB, 
           BreadA + BreadB, 
           WineA + WineB, 
           GrapesA + GrapesB ]); 
      end. 
3

很可能不是最有效的版本,由於壓縮和列表的追加,但假設他們沒有得到更長的時間,它不應該是明顯在大多數程序中,與可讀性的增加相比。

Process = fun([RockA, FishA, TreeA, BarkA, DogA, CowA, | RestA], 
       [RockB, FishB, TreeB, BarkB, DogB, CowB, | RestB]) -> 
       Start = if RockA =:= [0,0,0] -> 
          [RockB, FishB, TreeB, BarkB, DogB]; 
         true -> 
          [RockA, FishA, TreeA, BarkA, DogA] 
         end, 
       Start ++ [max(CowA, CowB)] ++ [X+Y || {X,Y} <- lists:zip(RestA, RestB)] 
      end. 

另請注意,當函數調用不匹配時,缺少catch-all子句。不要寫防禦性代碼。讓它崩潰並讓主管負責照顧它。編寫防禦代碼只會讓程序中的崩潰不是死刑的語言更難調試。

4

又一解決方案:

process([RockA, FishA, TreeA, BarkA, DogA | TlA], 
     [RockB, FishB, TreeB, BarkB, DogB | TlB]) -> 
    case RockA of 
    [0,0,0] -> [RockB, FishB, TreeB, BarkB, DogB | process2(TlA, TlB)]; 
    _  -> [RockA, FishA, TreeA, BarkA, DogA | process2(TlA, TlB)] 
    end. 

process2([CowA | TlA], [CowB | TlB]) -> 
    [erlang:max(CowA, CowB) | process3(TlA, TlB)]. 

process3([HdA | TlA], [HdB | TlB]) -> 
    [HdA + HdB | process3(TlA, TlB)]; 

process3([], []) -> []. 


Process = fun process/2. 
1

或者,採取捷思銳的回答與功能的條款,我們可以做到以下幾點更換的情況。我們找到了慣用的嗎?這很大程度上是品味和美感的問題。

process([[0,0,0], _, _, _, _ | TlA], 
     [RockB, FishB, TreeB, BarkB, DogB | TlB]) -> 
    [RockB, FishB, TreeB, BarkB, DogB | process2(TlA, TlB)]; 

process([RockA, FishA, TreeA, BarkA, DogA | TlA], 
     [_, _, _, _, _ | TlB]) -> 
    [RockA, FishA, TreeA, BarkA, DogA | process2(TlA, TlB)]. 

process2([CowA | TlA], [CowB | TlB]) -> 
    [erlang:max(CowA, CowB) | process3(TlA, TlB)]. 

process3([HdA | TlA], [HdB | TlB]) -> 
    [HdA + HdB | process3(TlA, TlB)]; 

process3([], []) -> []. 


Process = fun process/2. 
+0

我不認爲將條款從case語句移動到函數是更習慣的。我只選擇了案例陳述,因爲它比這更「可讀」。 – Zed 2010-06-24 16:37:51

+0

我不認爲'功能條款'的方法更習慣,我只是提出另一種選擇。我同意 - 在這種情況下,我認爲你的原件有點漂亮,儘管在大多數情況下,一個函數只包含一個case語句,但我通常會將其重構爲函數子句。這對我來說可能是一個例外,所以我給你+1。乾杯 – dsmith 2010-06-24 17:39:24