2013-03-19 45 views
3

Erlang全新。我試圖爲函數組合定義一些函數,例如compose,juxtpipe,但遇到了Erlang沒有(據我所知)可變參數這一事實,因此很難編寫一個可以工作的函數版本爲所有輸入。Erlang中缺少可變參數的變通辦法

到目前爲止,我的最好的辦法是硬編碼不同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))))))). 

其工作原理,但我很好奇,如果有更好的方法?

回答

3

問題是Erlang功能是由Name/Arity唯一標識的;例如,io:format/1io:format/2是兩個不同的功能。因此,可變參數函數根本不適合Erlang。

最乾淨的解決方案可能是你的建議。另一種選擇是編寫自定義的parsetransform(一個在解析之後但在編譯之前重寫AST的模塊)來捕獲並轉換對所需特定函數的調用,讓其他人通過非混亂的函數。轉換可以攔截諸如pipe(A1, A2, A3, ..., An)的呼叫並將其重寫爲pipe([A1, A2, A3, ..., An])

儘管如此:解析轉換可能很難得到正確的,並且必須在每個需要使用它們提供的功能的模塊中明確引用它們。 Basho的Lager日誌庫是一個很好用的解析轉換的例子。

+0

謝謝,解析轉換聲音有趣,我會看看。 – Russell 2013-03-19 22:38:37

+2

如果你確實下了解析轉換路線,請記住,擁有巨大權力會帶來巨大的責任。 – 2013-03-19 22:41:34

+1

看着它,我懷疑我會,我認爲我的硬編碼解決方案將足以覆蓋大多數情況,並且很難證明像邊緣情況下的解析變換這樣的東西。但是他們看起來很有趣。 – Russell 2013-03-19 22:44:06

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>