我处于这样一种情况,我只能创建分配给变量的匿名函数,如下所示:
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)
但这不起作用,因为我遇到"头部不匹配"错误.
简单而正确的答案是否定的,你做不到.当你这样做时,这实际上是非常符合逻辑的
foo(X) -> X.
foo(X, Y) -> X + Y.
Run Code Online (Sandbox Code Playgroud)
你实际上是在创建两个函数:foo/1一个参数的函数; 并且foo/2,另一个函数,它有两个参数.他们不一样foo.这直接映射到匿名函数(funs),因此您需要创建两个不同的函数,一个参数和两个参数中的另一个.
"头部不匹配"错误正在抱怨不同数量的参数.
您只能进行模式匹配:
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)
正如人们所期望的那样,性能显然取决于列表的长度,因为它必须遍历列表,并且损失比正常调用更大。
对我来说,性能差异看起来并不是那么大,但在大多数情况下,如果它是正确的解决方案,那么值得担心,至少,如果您不希望列表中有太多参数的话!