Syntax Erlang函数重载

Syntax Erlang函数重载,syntax,erlang,Syntax,Erlang,我刚开始摆弄二郎。 我见过很多在函数声明中使用模式匹配的示例,如: factorCount (N) -> Sqrt = math:sqrt (N), ISqrt = trunc(Sqrt), if ISqrt == Sqrt -> factorCount (N, ISqrt, 1, -1); true -> factorCount (N, ISqrt, 1, 0) end. factorCount (_N, ISqrt,

我刚开始摆弄二郎。 我见过很多在函数声明中使用模式匹配的示例,如:

factorCount (N) ->
   Sqrt = math:sqrt (N),
   ISqrt = trunc(Sqrt),
   if ISqrt == Sqrt -> factorCount (N, ISqrt, 1, -1);
      true          -> factorCount (N, ISqrt, 1, 0)
   end.

factorCount (_N, ISqrt, Candidate, Count) when Candidate > ISqrt -> Count;
factorCount ( N, ISqrt, Candidate, Count) ->
    case N rem Candidate of
        0 -> factorCount (N, ISqrt, Candidate + 1, Count + 2);
        _ -> factorCount (N, ISqrt, Candidate + 1, Count)
    end.
为什么要这样做?。 e、 g


为什么这不仅仅是一个内部有内部条件的函数?

一个原因是可读性和可维护性。函数内部的条件往往会由于额外的缩进而使代码向右爬行,而这些条件与正文中的额外条件相结合会导致较长的函数更难阅读、推理和维护

另一个原因是函数通常有先决条件,与嵌入函数体中的代码相比,Guard通常可以帮助更清楚地表达这些先决条件

还有一个原因是,模式匹配参数总是在调用函数时发生,因为函数参数基本上就是通过这种方式获得绑定的,所以在guards中使用这些绑定值是很自然的。Guards是模式匹配的一种扩展,允许您检查仅模式匹配无法检查的内容。

此外,如果我重写您的代码,这将更加明显:

factorCount(_N, ISqrt, Candidate, Count)
  when Candidate > ISqrt ->
    Count;
factorCount(N, ISqrt, Candidate, Count)
  when N rem Candidate =:= 0 ->
    factorCount(N, ISqrt, Candidate + 1, Count + 2);
factorCount(N, ISqrt, Candidate, Count) ->
    factorCount(N, ISqrt, Candidate + 1, Count).
在将模式匹配与一些防护措施相结合的代码中,这一点变得更加明显:

merge([{K, V1} | T1], [{K, V2} | T2]) ->
    [{K, [V1, V2]} | merge(T1, T2)];
merge([{K1, V1} | T1], [{K2, _} | _] = L2)
  when K1 < K2 ->
    [{K1, [V1]} | merge(T1, L2)];
merge(L1, [{K2, V2} | T2]) ->
    [{K2, [V2]} | merge(L1, T2)];
merge(L1, []) ->
    [{K, [V]} || {K, V} <- L1].
merge([{K,V1}| T1],{K,V2}| T2])->
[K[V1,V2]}合并(T1,T2)];
合并([{K1,V1}| T1],{K2,{u}| u]=L2)
当K1
[{K1[V1]}合并(T1,L2)];
合并(L1,[{K2,V2}T2])->
[K2[V2]}合并(L1,T2)];
合并(L1,[])->

[{K[V]}{K,V}但是老实说,我觉得Hynek的缩进看起来很难看,Lol4t0的缩进看起来很好,但是使用
if
s和最后的冗余测试使它看起来像是你刚从一种过程语言中来的。@NathanielWaisbrot这不是冗余测试,而是显式测试。显式总是比隐式好。@Lol4T0:正确的显式测试是正确的,但是原始代码中没有这样的测试,这可能是故意的。在您的代码中也缺少显式的<代码>候选=ISQRT < /代码>,如果实例,如果您想要显式的话,您也应该考虑。因此,版本似乎更习惯。无论如何,使用函数子句是一个MOR。由于模式匹配的广泛使用,这是一种常见的方法。您不希望在有和没有模式匹配的情况下使用不同的样式。@Hynek,首先,原始代码进行了显式测试。丢失的是您的代码。然后在这种特殊情况下,大量重载会产生大量重复,这是不好的。您已经得到了很好的答案,我将添加also也就是说,由于erlang广泛使用递归函数,在不同的子句中分离递归的不同情况是很方便的:就像这样,测试用例在第一行,递归调用(或基本情况的返回值)在每个子句的最后一行,每个子句都有一些注释,因此更易于阅读和维护。
merge([{K, V1} | T1], [{K, V2} | T2]) ->
    [{K, [V1, V2]} | merge(T1, T2)];
merge([{K1, V1} | T1], [{K2, _} | _] = L2)
  when K1 < K2 ->
    [{K1, [V1]} | merge(T1, L2)];
merge(L1, [{K2, V2} | T2]) ->
    [{K2, [V2]} | merge(L1, T2)];
merge(L1, []) ->
    [{K, [V]} || {K, V} <- L1].