Erlang缺乏varargs的解决方法

时间:2013-03-19 22:06:01

标签: erlang variadic-functions function-composition

Erlang全新。我正在尝试为函数组合定义一些函数,例如composejuxtpipe,但是遇到了Erlang没有(据我所知)varargs的事实,所以它是难以编写一个适用于所有输入的函数的一个版本。

到目前为止,我最好的想法是将不同arities的函数硬编码到合理的数量,并提供一个版本,列出更大的列表,如下所示:

pipe (X, Fs) when is_list(Fs) -> lists:foldl(fun (F, Acc) -> F(Acc) end, X, Fs);
pipe (X, F) -> F(X).
pipe (X, F, G) -> G(F(X)).
pipe (X, F, G, H) -> H(G(F(X))).
pipe (X, F, G, H, I) -> I(H(G(F(X)))).
pipe (X, F, G, H, I, J) -> J(I(H(G(F(X))))).
pipe (X, F, G, H, I, J, K) -> K(J(I(H(G(F(X)))))).
pipe (X, F, G, H, I, J, K, L) -> L(K(J(I(H(G(F(X))))))).

哪个有效,但我很好奇是否有更好的方法?

2 个答案:

答案 0 :(得分:4)

问题是Erlang函数由Name/Arity唯一标识;例如,io:format/1io:format/2是两个不同的函数。因此,可变函数根本不适合Erlang。

最干净的解决方案可能就是您的建议。另一种选择是编写一个自定义的parse transform(一个在解析之后但在编译之前重写AST的模块)来捕获和转换对你想要的特定函数的调用,让其他人通过unmolested。转换可以拦截pipe(A1, A2, A3, ..., An)之类的调用并将其重写为pipe([A1, A2, A3, ..., An])

请注意:解析转换很难正确,并且必须在需要使用它们提供的功能的每个模块中明确引用它们。一个充分利用的解析变换的例子是Basho的Lager日志库。

答案 1 :(得分:1)

我想知道为什么列表符号对你不好,因为它提供了一个非常简短的实现,类似于io:format / 2。

pipe (X, Fs) when is_list(Fs) -> lists:foldl(fun (F, Acc) -> F(Acc) end, X, Fs).
fibnext([A,B]) -> [A+B,A].


1> F = fun(X) -> my_module:fibnext(X) end.
#Fun<erl_eval.6.82930912>
2> my_module:pipe([1,1],lists:duplicate(12,F)).      
[377,233]
3>