Erlang尾递归,用于查找输入列表的每个列表中的元素数

时间:2017-01-14 07:18:34

标签: erlang

我如何在Erlang中使用尾递归来说我有列表[[1],[2],[3],[3,2]]并且我想输出列表[[1] ,[1],[1],[2]]其中输出列表中的每个列表代表输入列表中每个列表的元素数量?

我是函数式编程的初学者。

由于

1 个答案:

答案 0 :(得分:1)

我想这是一些家庭作业或自学习练习,通常使用库函数或本地erlang构造(例如列表理解)是个好主意:

List = [[1], [2], [3], [3,2]],
Result = lists:map(fun(X) -> [length(X)] end, List),
Result = [[length(X)] || X <- List],

这个问题的通常和直接的递归解决方案是

lengths_not_tail_recursive([]) -> []; % stop condition
lengths_not_tail_recursive([H|T]) -> [[length(H)]|lengths_not_tail_recursive(T)].

只要List不太大,这个解决方案就不那么糟糕了。它不是尾递归的,因为在递归的每一步,除了最后一步之外,“本地”工作的结果需要与后续步骤的结果相结合。

要解决这个问题,一般的解决方案是添加一个名为accumulator的新参数,它将在每一步记录到目前为止评估的内容,最后一步将返回最终和完整的结果。

lengths_tail_recursive([],Acc) -> lists:reverse(Acc); % stop condition
% the result needs to be reverse due to the way the accumulator is built at each step
lengths_tail_recursive([H|T],Acc) -> lengths_tail_recursive(T,[[length(H)]|Acc]).

不同之处在于,在每个递归步骤中,您只需返回下一步的结果,而无需修改。通常,此解决方案使用第二个函数,其作用是隐藏第二个参数的需要,并在第一次调用时正确初始化

lengths(L) -> lengths_tail_recursive(L,[]).

注意:尾递归解决方案使用2个库函数:length / 1和lists:reverse / 1。我邀请您以尾递归的方式编写它们