我正在尝试创建一个列表并打印出来,从N倒数到1.这是我的尝试:
%% Create a list counting down from N to 1 %%
-module(list).
-export([create_list/1]).
create_list(N) when length(N)<hd(N) ->
lists:append([N],lists:last([N])-1),
create_list(lists:last([N])-1);
create_list(N) ->
N.
当N为1时,这有效,但否则我收到此错误:
172> list:create_list([2]).
** exception error: an error occurred when evaluating an arithmetic expression
in function list:create_list/1 (list.erl, line 6)
任何帮助都将不胜感激。
答案 0 :(得分:4)
在构建列表时,通常应避免使用append
或++
,这是相同的事情。它们都会向列表的 end 添加元素,这需要每次都复制列表。有时它很实用,但在列表的前面工作总是更快。
有点不清楚你想要列表的顺序,所以这里有两个选择:
create_up(N) when N>=1 -> create_up(1, N). %Create the list
create_up(N, N) -> [N];
create_up(I, N) ->
[I|create_up(I+1, N)].
create_down(N) when N>1 -> %Add guard test for safety
[N|create_down(N-1)];
create_down(1) -> [1].
这些都不是尾递归的。虽然尾递归很好但它并不总是给你想象的多,特别是当你需要调用reverse
来获得正确顺序的列表时。有关详细信息,请参阅Erlang myths。
答案 1 :(得分:3)
错误为lists:last([N])-1
。由于N是一个数组作为输入,lists:last([N])
将返回N本身。不是你期望的数字。如果在编译代码时看到警告,则还有另一个错误:lists:append
不会将元素追加到N本身,而是返回值。在函数式编程中,变量的值不能改变。
这是我的实施:
create_list(N) ->
create_list_iter(N, []).
create_list_iter(N, Acc) ->
case N > 0 of
true -> NewAcc = lists:append(Acc, [N]),
create_list_iter(N-1, NewAcc);
false -> Acc
end.
答案 2 :(得分:3)
如果我正确理解您的问题,这就是您需要的内容
create_list(N) when N > 0 ->
create_list(N, []).
create_list(1, Acc) ->
lists:reverse([1 | Acc]);
create_list(N, Acc) ->
create_list(N - 1, [N | Acc]).
如果你使用列表,我建议你使用尾递归和列出构造语法。
另外,为简化代码 - 尝试在函数声明中使用使用模式匹配,而不是使用case表达式
<强> P.S。强> 另一个也许是最简单的解决方案是:
create_list(N) when N > 0 ->
lists:reverse(lists:seq(1,N)).