Erlang中是否可以使用多个匿名函数?

SCd*_*CdF 6 erlang

我处于这样一种情况,我只能创建分配给变量的匿名函数,如下所示:

Foo = fun(X) -> X end.
Run Code Online (Sandbox Code Playgroud)

我知道如果你在一个模块中,你可以做这样的事情:

foo(X) -> X.
foo(X, Y) -> X + Y.
% i.e. foo(3) = 3, foo(3,4) = 7
Run Code Online (Sandbox Code Playgroud)

我的问题是:这可以通过匿名函数实现吗?

一篇博文(我现在已经遗憾了)让我觉得你可以这样做:

Foo = fun(X) -> X;
         (X, Y) -> X + Y
      end.
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为我遇到"头部不匹配"错误.

rvi*_*ing 5

简单而正确的答案是否定的,你做不到.当你这样做时,这实际上是非常符合逻辑的

foo(X) -> X.
foo(X, Y) -> X + Y.
Run Code Online (Sandbox Code Playgroud)

你实际上是在创建两个函数:foo/1一个参数的函数; 并且foo/2,另一个函数,它有两个参数.他们一样foo.这直接映射到匿名函数(funs),因此您需要创建两个不同的函数,一个参数和两个参数中的另一个.

"头部不匹配"错误正在抱怨不同数量的参数.


Mic*_*ael 3

您只能进行模式匹配:

Foo = fun ({x,y}) -> one;
          ({a,b}) -> two
          end
Run Code Online (Sandbox Code Playgroud)

你可以只接受一个列表:

Foo = fun ([X])   -> X;
          ([X,Y]) -> {X,Y}
          end
Run Code Online (Sandbox Code Playgroud)

我很好奇,忍不住想看看它的性能,所以我快速对其进行了基准测试。这远非完美,只是为了表明可能的情况,实际上应该计算平均值、标准差、平均值、最小值和最大值,但我选择了执行 1,000,000 次调用的最短时间。

我使用了这段代码:

-module(foo).

-export([run/1, norm1/0, norm2/0, norm3/0, norm4/0, list1/0, list2/0, list3/0, list4/0]).

-define(COUNT, 1000000).


run(F) ->
    T = lists:foldl(
        fun(_,Min) ->
            T = ?MODULE:F(),
            if T < Min -> T; true -> Min end
            end,
        ?MODULE:F(),
        lists:seq(1,99)
        ),
    T
    .

norm1() ->
    Foo = fun(N) -> N * N end,
    {T,_} = timer:tc(fun() ->
        lists:map(fun(A) -> Foo(A) end, lists:seq(1,?COUNT))
        end),
    T
    .

norm2() ->
    Foo = fun(N, M) -> N * M end,
    {T,_} = timer:tc(fun() ->
        lists:map(fun(A) -> Foo(A,A) end, lists:seq(1,?COUNT))
        end),
    T
    .

norm3() ->
    Foo = fun(M, N, M) -> N * M end,
    {T,_} = timer:tc(fun() ->
        lists:map(fun(A) -> Foo(A,A,A) end, lists:seq(1,?COUNT))
        end),
    T
    .

norm4() ->
    Foo = fun(N, M, N, M) -> N * M end,
    {T,_} = timer:tc(fun() ->
        lists:map(fun(A) -> Foo(A,A,A,A) end, lists:seq(1,?COUNT))
        end),
    T
    .

list1() ->
    Foo = fun([N]) -> N * N end,
    {T,_} = timer:tc(fun() ->
        lists:map(fun(A) -> Foo([A]) end, lists:seq(1,?COUNT))
        end),
    T
    .

list2() ->
    Foo = fun([N, M]) -> N * M end,
    {T,_} = timer:tc(fun() ->
        lists:map(fun(A) -> Foo([A,A]) end, lists:seq(1,?COUNT))
        end),
    T
    .

list3() ->
    Foo = fun([_, N, M]) -> N * M end,
    {T,_} = timer:tc(fun() ->
        lists:map(fun(A) -> Foo([A,A,A]) end, lists:seq(1,?COUNT))
        end),
    T
    .

list4() ->
    Foo = fun([_, _, N, M]) -> N * M end,
    {T,_} = timer:tc(fun() ->
        lists:map(fun(A) -> Foo([A,A,A,A]) end, lists:seq(1,?COUNT))
        end),
    T
    .
Run Code Online (Sandbox Code Playgroud)

这是结果:

1> foo:run(norm1).
44820
2> foo:run(norm2).
48959
3> foo:run(norm3).
50328
4> foo:run(norm4).
50402
5> 
5> foo:run(list1).
50463
6> foo:run(list2).
58948
7> foo:run(list3).
60829
8> foo:run(list4).
86604
9> 
Run Code Online (Sandbox Code Playgroud)

正如人们所期望的那样,性能显然取决于列表的长度,因为它必须遍历列表,并且损失比正常调用更大。

对我来说,性能差异看起来并不是那么大,但在大多数情况下,如果它是正确的解决方案,那么值得担心,至少,如果您不希望列表中有太多参数的话!