Erlang sumif函数

时间:2016-05-01 05:09:41

标签: erlang

我正在尝试在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.

我尝试将possumif一起使用,但我收到此错误:

exception error: bad function pos

为什么会这样?是因为我的sumif函数还是pos?我已经自己测试了pos,它看起来效果很好。

编辑:可能是因为我正在调用该函数。这就是我目前正在调用的方式:hi:sumif(pos,[-1,1,2,-3]).其中hi是我的模块名称。

3 个答案:

答案 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)]).

Dobertanswer是正确的,问题是你的空列表的总和。

如果您的关注点是性能,那么您应该坚持使用尾递归解决方案(在这种情况下,这很重要,因为没有涉及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