2016-05-01 6 views
0

Ich versuche, eine sumif Funktion in Erlang, die eine Summe aller Elemente in einer Liste zurückgeben würde, wenn die Prädikatfunktion als wahr ausgewertet wird. Hier ist, was ich habe:Erlang Sumif Funktion

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

ich auch meine eigene POS-Funktion implementiert, die true zurückgibt, wenn eine Zahl größer als 0 ist und ansonsten false:

pos(A) -> A > 0. 

ich versucht, mit pos mit sumif aber ich m Erhalte diesen Fehler:

exception error: bad function pos 

Warum passiert das? Ist es wegen meiner Funktion oder pos? Ich habe pos auf eigene Faust getestet und es scheint gut zu funktionieren.

Edit: Es könnte sein, weil, wie ich die Funktion aufrufen. So nenne ich es gerade: hi:sumif(pos,[-1,1,2,-3]). Wobei hi mein Modulname ist.

Antwort

3

Is it because of my sumif function or pos?

Es ist wegen sumif. Sie sollten 0 zurück, wenn eine leere Liste geführt wird, wie es aus der zweiten Klausel genannt werde, wenn T[] ist:

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

Test:

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

Vielen Dank. Es ist auch, weil die Art, wie ich die 'pos'-Funktion aufgerufen habe, auch falsch ist. Habe gerade etwas Neues gelernt! – Ccyan

2

Liste Comprehensions Dinge viel einfacher machen:

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

Dobert ‚s answer von cousrse richtig ist, Problem ist Ihre Summe für leere Liste.

Wenn Ihr Anliegen Leistung ein wenig ist, sollten Sie am Ende rekursive Lösung bleiben (in diesem Fall ist es wichtig, weil es nicht lists:reverse/1 beteiligt ist).

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

Wege, wie die korrekte Funktion für den ersten Parameter zu machen:

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

Schlepptau Fehler gibt in Ihrem Code hat: 1. sumif(_, []) -> undefined; sollte 0 zurückkehren, nicht undefined. 2. wenn Sie pos(A) -> A > 0.-sumif/2 passieren, sollten Sie fun pos/1 verwenden, lesen Sie bitte 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). 

Sie lists:foldl verwenden können.

Verwandte Themen