从N减少到1

时间:2012-12-14 10:58:03

标签: erlang

我正在尝试创建一个列表并打印出来,从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)

任何帮助都将不胜感激。

3 个答案:

答案 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)).