Completely new to Erlang. I'm trying to define some functions for function composition, such as compose
, juxt
and pipe
but running into the fact that Erlang doesn't have (to my knowledge) varargs so it's difficult to write just one version of such functions that will work for all inputs.
So far my best idea is to hardcode functions of different arities up to a reasonable number, as well as providing a version that takes a list for anything bigger, like this:
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))))))).
which works, but I'm curious if there's a better way?
The problem is that Erlang functions are uniquely identified by Name/Arity
; io:format/1
and io:format/2
, for instance, are two different functions. Hence, variadic functions simply don't fit into Erlang.
The cleanest solution is probably what you suggested. Another option is to write a custom parse transform (a module that rewrites the AST after parsing but before compilation) to catch and transform calls to the specific functions you want, letting others pass through unmolested. The transform could intercept calls like pipe(A1, A2, A3, ..., An)
and rewrite them to pipe([A1, A2, A3, ..., An])
.
Be warned though: Parse transforms can be difficult to get right, and they must be explicitly referenced in every module that needs to use the features they provide. An example of parse transforms put to good use is Basho's Lager logging library.
I wonder why the list notation is not good for you, because it gives a very short and easy implementation, similar to the 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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With