Erlang风格 - 案例与功能模式匹配

时间:2009-06-26 19:48:27

标签: coding-style erlang

我已经到了现在我写了很多Erlang代码的阶段,我可以看到一些风格(坏或好)悄悄进入我写作的方式。这个特定的习惯用法我想要一些意见 - 将案例样式语句转换为函数模式匹配更好(更可读/更快/更好)?

E.g。

比较(一个人为的例子)

case {Size > 100000, Type} of
    {true, ets } ->
         %% Do something to convert to dets
         something;
    {false, dets} ->
         %% do something to convert to ets
         somethingelse;
    _ ->
         ignoreit
end;

...
maybeChangeStorage(Size, Type)
...

maybeChangeStorage(Size, ets) when Size > 10000 ->
   something;
maybeChangeStorage(Size, dets) when Size < 10000 ->
   somethingelse;
maybeChangeStorage(_,_) ->
   ignoreit.

在大多数情况下,我更喜欢后者,但我对其他观点感兴趣。

6 个答案:

答案 0 :(得分:14)

第二种是首选方式,尤其是如果您可以将子句保留在一行中:

maybeCngStor(Sz, ets)  when Sz > 10000 -> something;
maybeCngStor(Sz, dets) when Sz < 10000 -> somethingelse;
maybeCngStor(_,_)                      -> ignoreit.

使阅读和推理变得非常容易。始终选择将来最容易阅读的风格。通常你会发现一组子句,其中一个是10个衬里,其余的只有一行 - 将长的一个分成一个函数:

maybeCngStor(Sz, ets)  when Sz > 10000 -> something;
maybeCngStor(Sz, dets) when Sz < 10000 -> somethingelse();
maybeCngStor(_,_)                      -> ignoreit.

somethingelse() ->
   (...)
   Return.

诸如布置条款以使它们对齐并使用短变量名称之类的小事情很重要 - 但不要陷入将所有内容更改为P,Q,R的陷阱。

如果你经常使用记录,那么一个很好的技巧就是将记录与短变量相匹配:

#record{foo = F, bar = B, baz = Bz} = Parameter

这为您提供了一些简短的变量名称,当您从下一个圣诞节的10,000英尺处跳伞查找错误时,这些名称是有意义的。 F显然是Foo等等...

答案 1 :(得分:7)

Learn you some Erlang for great goodsmall section时间选择case以及何时使用function。提到了两件事:

  1. 它们在VM中以相同的方式表示,因此两种解决方案之间的性能没有差异。

  2. 如果你需要对多个参数使用防范,使用函数可能会更好。

  3. 总而言之,这主要是风格和品味的问题。

答案 2 :(得分:3)

您可以通过以下方式使这些示例更相似:

case Type of
   ets  when Size > 10000 -> ...;
   dets when Size < 10000 -> ...;
   _ -> ...
end.

这对我来说似乎更清晰。将其拆分为单独的函数的优点是,您可以为其指定一个名称,该名称充当文档并显示在堆栈跟踪中。如果该片段是较大功能的一部分,我会将其分开,否则它就可以了。

值得考虑的一件事是,写入函数的错误情况将接受除ets / dets之外的Type参数。除非这真的是你想要的,否则值得使这个条款更具限制性。

答案 3 :(得分:0)

至于我,第一种风格更清晰,可能更快。但它需要测试才能准确地说出来。 在第二种情况下,如果键入!= ets,则将评估“Size&gt; 10000”和“Size&lt; 10000”。

答案 4 :(得分:0)

(作为获取代码格式的答案......!)

当我做出一些改变时,我发现的一件事是 这种方法可以改变默认的短路。例如。

case A > 10 of 
      true -> 
             case B > 10 of 
                  true -> dummy1; 
                  false -> dummy2 
             end; 
      false -> dummy3 
end 

必须始终执行B&gt; 10,如果你称之为

doTest(A > 10, B > 10) 

何时

doTest(true, true) -> dummy1; 
doTest(true, false) -> dummy2; 
doTest(false, _) -> dummy3. 

有时候不是你想要的!

答案 5 :(得分:0)

如果你在函数中首先要做的是打开一个case子句,最好将这个顶级子句转换为函数模式匹配。