【问题标题】:Workarounds for lack of varargs in ErlangErlang 中缺少可变参数的解决方法
【发布时间】:2013-03-08 19:57:20
【问题描述】:

对 Erlang 来说是全新的。我正在尝试为函数组合定义一些函数,例如composejuxtpipe,但遇到了 Erlang 没有(据我所知)可变参数的事实,因此很难只编写一个版本适用于所有输入的此类函数。

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

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))))))).

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

【问题讨论】:

    标签: erlang variadic-functions function-composition


    【解决方案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>
    

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 谢谢,解析转换听起来很有趣,我会看看。
      • 如果你确实走上了解析转换的路线,请记住,能力越大,责任越大。
      • 看着它我怀疑我会,我认为我的硬编码解决方案足以涵盖大多数情况,而且很难证明边缘情况的解析转换之类的东西......但它们看起来很有趣关于。
      • github.com/uwiger/parse_trans 如果您沿着解析转换路线走下去会很有帮助
      猜你喜欢
      • 2016-10-19
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-29
      • 2014-03-16
      • 1970-01-01
      • 2016-09-20
      相关资源
      最近更新 更多