我正在尝试创建一个带有关联和可交换运算符的方法,以及一个值列表,然后通过将运算符应用于列表中的值来返回答案。
以下两个示例表示输入/输出应该是什么样子。
示例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)此外,代码如何在没有列表功能的情况下实现,或者以更连续的方式实现?
答案 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}}