2016-05-01 75 views
0

我試圖在Erlang中創建一個sumif函數,如果謂詞函數的計算結果爲true,它將返回列表中所有元素的總和。以下是我有:Erlang sumif函數

sumif(_, []) -> undefined; 
sumif(Fun, [H|T]) -> case Fun(H) of 
         true -> H + sumif(Fun, T); 
         false -> sumif(Fun, T) 
        end. 

我還執行了返回true,如果數大於0,否則爲假我自己的POS功能:

pos(A) -> A > 0. 

我嘗試使用possumif但我m得到這個錯誤:

exception error: bad function pos 

爲什麼會發生這種情況?是因爲我的sumif函數還是pos?我自己測試了pos,它似乎工作得很好。

編輯:這可能是因爲我如何調用函數。這就是我目前所說的:hi:sumif(pos,[-1,1,2,-3]).其中hi是我的模塊名稱。

回答

3

Is it because of my sumif function or pos?

這是因爲sumif。您應該返回0時傳遞一個空列表,因爲它會從第2節時調用T[]

-module(a). 
-compile(export_all). 

sumif(_, []) -> 0; 
sumif(Fun, [H|T]) -> case Fun(H) of 
         true -> H + sumif(Fun, T); 
         false -> sumif(Fun, T) 
        end. 

pos(A) -> A > 0. 

測試:

1> c(a). 
{ok,a} 
2> a:sumif(fun a:pos/1, [-4, -2, 0, 2, 4]). 
6 
+0

謝謝。這也是因爲我稱之爲pos函數的方式也是錯誤的。剛剛學到了新東西! – Ccyan

2

列表理解讓事情變得簡單得多:

sumif(F, L) -> 
    lists:sum([X || X <- L, F(X)]). 

Dobertanswer是cousrse的權利,問題是你的總數空列表。

如果你的擔心是性能有點你應該堅持尾遞歸解決方案(在這種情況下,因爲沒有涉及lists:reverse/1重要)。

sumif(F, L) -> 
    sumif(F, L, 0). 

sumif(F, [], Acc) when is_function(F, 1) -> Acc; 
sumif(F, [H|T], Acc) -> 
    New = case F(H) of 
      true -> H+Acc; 
      false -> Acc 
     end, 
    sumif(F, T, New). 

方式如何作出正確的函數的第一個參數:

F1 = fun pos/1,  % inside module where pos/1 defined 
F2 = fun xyz:pos/1, % exported function from module xyz (hot code swap works) 
N = 0, 
F3 = fun(X) -> X > N end, % closure 
% test it 
true = lists:all(fun(F) -> is_function(F, 1) end, [F1, F2, F3]). 
0

在有你的代碼有錯誤拖: 1. sumif(_, []) -> undefined;應該返回0,不undefined。 2.當你通過pos(A) -> A > 0.sumif/2,你應該使用fun pos/1,請閱讀http://erlang.org/doc/programming_examples/funs.html#id59138

sumif(F, L) -> 
    lists:foldl(fun(X, Sum) when F(X) -> Sum+X; (_) -> Sum end, 0, L). 

您可以使用lists:foldl