Si può solo pattern match:
Foo = fun ({x,y}) -> one;
({a,b}) -> two
end
Si può solo accettare una lista:
Foo = fun ([X]) -> X;
([X,Y]) -> {X,Y}
end
ero troppo curioso di non guardare le prestazioni, così ho avuto un rapido andare a benchmark esso. Questo è tutt'altro che perfetto, e inteso solo per essere indicativo di ciò che potrebbe essere, e in realtà si dovrebbe calcolare una media, deviazione standard, media, minima e massima, ma ho optato per un tempo minimo per fare 1.000.000 di chiamate.
Ho usato questo codice:
-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
.
Questo è il risultato:
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>
Le prestazioni sono ovviamente andando a dipendere da quanto tempo la lista è, come ci si aspetterebbe, in quanto deve lavorare attraverso la lista e la penalità è maggiore rispetto a una chiamata normale.
La differenza di prestazioni non mi sembra così grande per quanto valga la pena di preoccuparsi nella maggior parte delle situazioni se è la soluzione corretta, almeno, se non ci si aspetta di avere troppi argomenti nelle proprie liste!
È possibile farlo solo per la corrispondenza di modelli, ad esempio 'Foo = fun ({x, y}) -> uno; ({a, b}) -> two end', non riesco a pensare a un modo in cui puoi fare ciò che vuoi a meno che tu non accetti semplicemente una lista, come 'Foo = fun ([X]) -> X; ([X, Y]) -> {X, Y} fine', chiamando 'Foo ([a])' e 'Foo ([a, b])', ecc. – Michael
Sì, a parte accettare una lista non riesco a trovare nulla. Nella situazione del mondo reale, ciascuna delle variabili passate sono cose diverse, quindi un'opzione sarebbe quella di passare una lista (io penso che sia una mappa idiomatica, io sono nuovo di Erlang) e farlo in quel modo. Fai del tuo commento una risposta se vuoi un dolce dolce karma: P – SCdF
In realtà è una domanda molto interessante, non ho mai notato o pensato a questo ... – Michael