Erlang:累加器的串行实现

时间:2018-04-17 15:07:19

标签: erlang

我正在尝试创建一个带有关联和可交换运算符的方法,以及一个值列表,然后通过将运算符应用于列表中的值来返回答案。

以下两个示例表示输入/输出应该是什么样子。

示例1

Input: sum(fun(A,B) -> A+B end, [2,6,7,10,12]).

Output: 37

示例2

Input: sum(fun (A,B) -> A++B end , ["C", "D", "E"]).

Output: "CDE"

这是我目前使用的代码。

-module(tester).
-compile(export_all).

sum(Func, Data, Acc) ->
    lists:foldr(Func, Acc, Data).

此代码生成正确的结果,但是,我试图找出如何处理回答有两个问题。

(1)为了使此代码有效,它需要在命令行语句的末尾包含空列表。换句话说,如果我输入上面的输入(如示例中所示),它将会出错,因为我没有按以下方式编写它:

12> tester:sum(fun(X, Acc) -> X+Acc end, [2,6,7,10,12], 0).

如果没有上面示例中的空列表,我将如何实现此目的并获得相同的结果?

(2)此外,代码如何在没有列表功能的情况下实现,或者以更连续的方式实现?

2 个答案:

答案 0 :(得分:5)

  

如果没有上面示例中的空列表,我将如何实现此目的并获得相同的结果?

假设列表总是有一个元素(没有这个假设你真的不能这样做),你可以从列表中提取第一个元素并将其作为初始累加器传递。您需要切换到foldl才能有效地执行此操作。 (使用foldr,您基本上需要复制列表以删除最后一个元素。)

sum(Func, [X | Xs]) ->
  lists:foldl(fun (A, B) -> Func(B, A) end, X, Xs).
1> a:sum(fun(A,B) -> A+B end, [2,6,7,10,12]).
37
2> a:sum(fun (A,B) -> A++B end , ["C", "D", "E"]).
"CDE"
  

此外,如何在没有列表功能的情况下实现代码,或者以更连续的方式实现代码?

这是一个使用递归和模式匹配的简单实现:

sum2(Func, [X | Xs]) ->
  sum2(Func, Xs, X).

sum2(Func, [], Acc) ->
  Acc;
sum2(Func, [X | Xs], Acc) ->
  sum2(Func, Xs, Func(Acc, X)).

我们定义了两个版本的函数。第一个提取头部并将其用作初始累加器。第二个,具有arity 3,基本上完成了lists中的折叠函数。

答案 1 :(得分:0)

一段时间后,这是我的解决方案。关于我所做工作的总体想法,我已经发表了一些评论,但还有很多话要说。

{{1}}