【发布时间】:2017-01-14 16:33:41
【问题描述】:
我如何在 Erlang 中使用尾递归来表示我有列表 [[1], [2], [3], [3,2]] 并且我想输出列表 [[1], [ 1], [1], [2]] 其中输出列表中的每个列表代表输入列表中每个列表的元素数?
我是函数式编程的初学者。
谢谢
【问题讨论】:
-
显示你尝试过的代码。
标签: erlang
我如何在 Erlang 中使用尾递归来表示我有列表 [[1], [2], [3], [3,2]] 并且我想输出列表 [[1], [ 1], [1], [2]] 其中输出列表中的每个列表代表输入列表中每个列表的元素数?
我是函数式编程的初学者。
谢谢
【问题讨论】:
标签: erlang
我想这是一些家庭作业或自学练习,通常使用库函数或本地 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 不太大,这个解决方案还不错。它不是尾递归,因为在递归的每一步,除了最后一步,“本地”工作的结果都需要与后续步骤的结果相结合。
为了解决这个问题,一般的解决方法是增加一个新的参数,叫做累加器,它会在每一步记录到目前为止评估的内容,最后一步会返回最终的完整结果。
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。我邀请您以尾递归的方式编写它们
【讨论】: