[erlang-questions] Re: Nested for-loops, there has to be a better way to do this

Joe Armstrong erlang@REDACTED
Fri Jul 31 15:34:35 CEST 2009


I still don't understand. Erlang (or any functional programming languages)
is made from lots of small functions. Each function has inputs and outputs
and there is some relationship between the inputs and the output.

To specify a function we must state what the inputs are, state what
the outputs are and state what the relationship between the inputs and
outputs are.

The fact that you print something is irrelevant. You could just as
well say that the
output of a function is a list and that you then print the items in the list one
at a time.

I have tried to write a program that *exactly* follows your spec.
Following the rules in your spec I conclude that if the input to your program
is the list [4,2,1,1] then the output should be [4,2,1,5,4,3,2,1,1,3,2,1]

Is this correct?

Here's the program - read the comments to see how the code relates to the spec.

-module(process).

-compile(export_all).

test() ->
    process([4,2,1,5]).

process(In) ->
    Out = f(In),
    [io:format("~p~n", [I]) || I <- Out].

%% Now we have to write f
%% The spec says this:

%% Takes first int, processes it (in this case, prints it out),
%% decrements it, takes the second int, processes it (prints it out),
%% decrements it and on.  When it gets to the very last item, it
%% processes it until there are none left.  Then goes to the one above
%% it, processes it, decrements it... wash, rinse, repeat :) .

%% What this mean ... lets' take it bit by bit.

%% The first two lines say
%% Takes first int, processes it (in this case, prints it out),
%% decrements it, takes the second int, processes it (prints it out),

%% What happens after the first int has been decremented?
%% Now we have to "take the second int" wheres the first Int gone?
%% It seems like it is pushed onto a stack, so we can deal with it later.
%% The idea of a stack is reinforced by saying later "goes to the one above"

%% So here's what I think the first two lines of the spec mean:

f(L) -> process(L, [], []).

process([Int|T], Stack, Print) ->
    %% Takes first int, processes it (in this case, prints it out),
    %% decrements it, takes the second int, processes it (prints it out),
    process(T, [Int-1|Stack], [Int|Print]);

%% Now we get to the next major bit of the spec
%%  .. When it gets to the very last item, it
%%  .. processes it until there are none left.  Then goes to the one above
%% .. it, processes it, decrements it... wash, rinse, repeat :) .

%% This is very confusing. The word "it" is referred to many times
%% What is "it".
%% "when it gets to the very last item, it process it until there are non left"

%% But if it has got to the very last item there there is nothing to process
%% because it is the last item.

%% To resolve this we look at the next lines of the spec
%% " When it gets to the very last item, it
%%   processes it until there are none left.  Then goes to the one above
%%   it, processes it, decrements it... wash, rinse, repeat :) .

%% I think this means this:
process([], [H|Rest], Print) when H > 0->
    process([], [H-1|Rest], [H|Print]);

%% All this talk of decrementing things makes me wonder
%% how the iteration will stop I assume it's when
%% "it" reaches zero which is why I added the guard above.
%% Let's add a base case

process([], [0|Rest], Print) ->
    process([], Rest, Print);

%% Finally when "it" is zero and "there is nothing above"

process([], [], Print) ->
    lists:reverse(Print).

%% end

Incidentally if you had given a test case
i.e that for the input  [4,2,1,1] then the output should be
[4,2,1,5,4,3,2,1,1,3,2,1]

Then I would have immediately translated this into a unit test:

   test() ->
        [4,2,1,5,4,3,2,1,1,3,2,1] = f([4,2,1,1]).

*before* writing the code

Cheers

/Joe



On Fri, Jul 31, 2009 at 3:59 AM, Yves S.
Garret<yoursurrogategod@REDACTED> wrote:
> Takes first int, processes it (in this case, prints it out),
> decrements it, takes the second int, processes it (prints it out),
> decrements it and on.  When it gets to the very last item, it
> processes it until there are none left.  Then goes to the one above
> it, processes it, decrements it... wash, rinse, repeat :) .
>
> In retrospect, I could have made this clearer.
>
>
> On Jul 29, 2:35 am, Joe Armstrong <erl...@REDACTED> wrote:
>> I don't understand what you want.
>>
>> If the input to your program is: [5,5,10]
>> the output should be: X
>>
>> What is X?
>>
>> /Joe
>>
>> On Wed, Jul 29, 2009 at 4:55 AM, Yves S.
>>
>>
>>
>>
>>
>> Garret<yoursurrogate...@REDACTED> wrote:
>> > I was playing around with the idea of implementing a nested for-loop
>> > like construct (I will concede, they are evil, but at rare times,
>> > necessary.)  In non-functional programming languages, they are trivial
>> > to do.  However, this has proved to be one of those simple things that
>> > are a pain in the neck for me.  The idea was to be able to pass in a
>> > list [5, 5, 10] (for example) and go through it all like 3 dimensional
>> > array.  The below illustration is far from elegant (it's almost 23:00
>> > where I live and need to go to work tomorrow early, so no time to come
>> > up with something more sane :) ), but is there as an inquisitive
>> > exercise.  Now, in my opinion, this implementation sucks (first time
>> > I've ever gave such a problem a shot in Erlang.)
>>
>> > Is there a better way to do this?  Anyone would like to demonstrate
>> > it?
>>
>> > Note: I've tested this code with the lists [2, 4] and [2, 4, 5].
>>
>> > Compiled with:
>> > Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 5.6.5
>>
>> > My code:
>> > ======================================
>> > -module(loopWrapper).
>>
>> > -export([runLoop/1]).
>>
>> > runLoop(List) ->
>> >  [FirstVal | RestList] = List,
>> >  NextVal = FirstVal - 1,
>> >  if (length(RestList) > 0) and (FirstVal > 0) ->
>> >    io:format("~B~n~n", [FirstVal]),
>> >    runLoop(RestList),
>> >    io:format("~n~n"),
>> >    runLoop([NextVal | RestList]);
>> >  FirstVal > 0 ->
>> >    io:format("~B", [FirstVal]),
>> >    runLoop([NextVal]);
>> >  true ->
>> >    null
>> >  end.
>>
>> > ________________________________________________________________
>> > erlang-questions mailing list. Seehttp://www.erlang.org/faq.html
>> > erlang-questions (at) erlang.org
>>
>> ________________________________________________________________
>> erlang-questions mailing list. Seehttp://www.erlang.org/faq.html
>> erlang-questions (at) erlang.org
>
> ________________________________________________________________
> erlang-questions mailing list. See http://www.erlang.org/faq.html
> erlang-questions (at) erlang.org
>
>


More information about the erlang-questions mailing list