我正在尝试在Erlang中创建一个sumif
函数,如果谓词函数的计算结果为true,它将返回列表中所有元素的总和。这就是我所拥有的:
sumif(_, []) -> undefined;
sumif(Fun, [H|T]) -> case Fun(H) of
true -> H + sumif(Fun, T);
false -> sumif(Fun, T)
end.
我还实现了自己的pos函数,如果数字大于0则返回true,否则返回false:
pos(A) -> A > 0.
我尝试将pos
与sumif
一起使用,但我收到此错误:
exception error: bad function pos
为什么会这样?是因为我的sumif
函数还是pos
?我已经自己测试了pos
,它看起来效果很好。
编辑:可能是因为我正在调用该函数。这就是我目前正在调用的方式:hi:sumif(pos,[-1,1,2,-3]).
其中hi
是我的模块名称。
答案 0 :(得分:3)
是因为我的sumif函数还是pos?
这是因为sumif
。传递空列表时应返回0
,因为当T
为[]
时,它将从第2个子句调用:
-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
答案 1 :(得分:2)
列表理解使事情变得更加简单:
sumif(F, L) ->
lists:sum([X || X <- L, F(X)]).
Dobert的answer是正确的,问题是你的空列表的总和。
如果您的关注点是性能,那么您应该坚持使用尾递归解决方案(在这种情况下,这很重要,因为没有涉及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]).
答案 2 :(得分: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
。