Erlang:累加器的串行实现

rev*_*010 0 erlang

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

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

例1

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

Output: 37
Run Code Online (Sandbox Code Playgroud)

例2

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

Output: "CDE"
Run Code Online (Sandbox Code Playgroud)

这是我目前正在使用的代码.

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

sum(Func, Data, Acc) ->
    lists:foldr(Func, Acc, Data).
Run Code Online (Sandbox Code Playgroud)

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

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

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

如何在没有上面示例中的空列表的情况下实现此目的并得到相同的结果?

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

Dog*_*ert 5

如何在没有上面示例中的空列表的情况下实现此目的并得到相同的结果?

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

sum(Func, [X | Xs]) ->
  lists:foldl(fun (A, B) -> Func(B, A) end, X, Xs).
Run Code Online (Sandbox Code Playgroud)
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"
Run Code Online (Sandbox Code Playgroud)

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

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

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

sum2(Func, [], Acc) ->
  Acc;
sum2(Func, [X | Xs], Acc) ->
  sum2(Func, Xs, Func(Acc, X)).
Run Code Online (Sandbox Code Playgroud)

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