6

From "Erlang Programming" by Cesarini exercise 3-2

As I go through "Erlang Programming" I get weird list creation issues. From exercise 3-2 I wrote two similar functions.

create( 0 ) -> [];
create( N ) when N > 0 -> [ N | create( N-1 ) ].

reverse_create( 0 ) -> [];
reverse_create( N ) when N > 0 -> [ reverse_create( N-1 ) | N ].

so create(3) generates as I'd expect.

exercise3:create(3).
[3,2,1]

but reverse_create does not generate the list I expect.

exercise3:reverse_create(3).
[[[[]|1]|2]|3]

What do I need to change so that reverse_create(3) returns [1,2,3]? Thanks for explaining.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
Superpolock
  • 3,515
  • 7
  • 30
  • 24
  • OK, got the example working. Any clue why the two similar functions above return such different answers? Why does create return a clean list while reverse_create returns lists of lists? – Superpolock Nov 20 '10 at 08:43
  • you can read this for explanation: http://learnyousomeerlang.com/starting-out-for-real#lists and also look at these: http://stackoverflow.com/questions/3232786/how-to-concat-lists-in-erlang-without-creating-nested-lists and http://stackoverflow.com/questions/1919097/functional-programming-what-is-an-improper-list – Peer Stritzinger Nov 20 '10 at 18:56

5 Answers5

5

reverse_create returns a list and you using that as head element to create the list which is resulting in nested lists. Try this solution:

reverse_create( 0 ) -> [];
reverse_create( N ) when N > 0 -> reverse_create( N-1 ) ++ [N].

EDIT: A much better implementation would be:

reverse_create2(N) -> reverse_create_helper(N, []).

reverse_create_helper(0, Acc) ->
    Acc;
reverse_create_helper(N, Acc) ->
    reverse_create_helper(N-1, [N|Acc]).
Chandra Patni
  • 17,347
  • 10
  • 55
  • 65
3

Normally a function such as reverse_create would be done in a tail-recursive fashion with an accumulator.

reverse_create(N) ->
    reverse_create(N, []).

reverse_create(0, Acc) ->
    Acc;
reverse_create(N, Acc) when N > 0 ->
    reverse_create(N - 1, [N | Acc]).
2

Of course, you could always do:

reverse_create(N) -> lists:reverse(create(N)).

This would actually run faster. But that obviously isn't the intent of the exercise. :)

OJ.
  • 28,944
  • 5
  • 56
  • 71
1

I'm reading the same book, so I'm no more expert than you, but this worked for me...

create(0) -> [];
create(N) when N > 0 -> create(N-1) ++ [N].

reverse_create(0) -> [];
reverse_create(N) when N > 0 -> [N|create(N-1)].
Felix
  • 699
  • 2
  • 9
  • 24
0

This is



    reverse_create(0) -> [];
    reverse_create(N) ->
        list_create_1(1, N, []).

    list_create_1(I, N, List) when N >= I ->
        list_create_1(I + 1, N, [I | List]);
    list_create_1(_, _, List) -> List.


ololo
  • 1