我在这里有一个Erlang片段,我想研究更多惯用的Erlang,而不是粗略的Python翻译。
进程采用一对全等列表并将它们组合在一起。某些元素需要根据其属性从一个列表或另一个列表中获取,而其余元素需要求和。它运作正常,但我觉得这不是惯用的......
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.
答案 0 :(得分: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 :(得分: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子句。不要写防守代码。让它崩溃并由主管负责。编写防御性代码只会使一个语言中的调试变得更难,因为崩溃不是程序中的死刑。
答案 2 :(得分:1)
以下是一些建议。但是你喜欢中间变量赋值是一个品味问题。请注意'case'和'if'是总是评估某些东西的表达式。我还删除了“(,) - &gt; ok”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 :(得分:1)
或者,采用Zed的答案并用函数子句替换案例,我们可以执行以下操作。我们找到了惯用的吗?大部分都是品味和审美的问题。
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.