2010-06-24 114 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