我处于这样一种情况:我只能创建分配给变量的匿名函数,如下所示:
Foo = fun(X) -> X end.
我知道如果你在一个模块中,你可以做这样的事情:
foo(X) -> X.
foo(X, Y) -> X + Y.
% i.e. foo(3) = 3, foo(3,4) = 7
我的问题是:这可能是匿名函数吗?
一篇博文(我现在已经遗憾了)让我觉得你可以这样做:
Foo = fun(X) -> X;
(X, Y) -> X + Y
end.
但这不起作用,因为我遇到“头部不匹配”错误。
答案 0 :(得分:5)
简单而正确的答案是不,你不能。这实际上非常合乎逻辑,就像你做的那样
foo(X) -> X.
foo(X, Y) -> X + Y.
您实际上正在创建两个函数:foo/1
,一个参数的函数;和foo/2
,另一个有两个参数的函数。他们不相同foo
。这直接映射到匿名函数(funs
),因此您需要创建两个不同的函数,一个参数中的一个和两个参数中的另一个。
"头部不匹配"错误是抱怨不同数量的论点。
答案 1 :(得分:2)
你只能模式匹配:
Foo = fun ({x,y}) -> one;
({a,b}) -> two
end
你可以接受一个清单:
Foo = fun ([X]) -> X;
([X,Y]) -> {X,Y}
end
我太好奇了,不去看表演,所以我快速进行基准测试。这远非完美,只是为了表明可能是什么,而且实际上应该计算平均值,标准偏差,平均值,最小值和最大值,但我选择了最少的时间来进行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
.
结果如下:
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>
性能显然取决于列表的长度,正如人们所期望的那样,因为它必须通过列表工作,并且惩罚大于正常调用。
虽然在大多数情况下,如果它是正确的解决方案,那么性能差异对我来说并不是那么大,至少,如果你不希望你的列表中有太多的参数!