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

Brentley Jones <>
Wed Jul 29 20:12:12 CEST 2009


This is my take on it:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(for).

-export([for/4, test_1/0, test_2/0]).

for(BodyFun, Acc, ConditionFun, StepFun) ->
   Done = ConditionFun(Acc),
   if Done == false ->
        Acc;
      true ->
        NewAcc = BodyFun(Acc),
        LastAcc = StepFun(NewAcc),
        for(BodyFun, LastAcc, ConditionFun, StepFun)
   end.

test_1() ->
   Body = fun(I) ->
            io:format("i=~p~n", [I]),
            I
          end,
   for(Body, 0, fun(I) -> I < 10 end, fun(I) -> I + 1 end),
   ok.

test_2() ->
   CondFun = fun(X) -> X < 5 end,
   StepFun = fun(X) -> X + 1 end,
   BodyInner = fun(J) ->
                 io:format("~p", [J]),
                 J
               end,
   BodyOuter = fun(I) ->
                 for(BodyInner, 0, CondFun, StepFun),
                 io:format("~n"),
                 I
              end,
  for(BodyOuter, 0, CondFun, StepFun),
  ok.


%%%%% Output:
2> for:test_2().
01234
01234
01234
01234
01234
ok
3> for:test_1().
i=0
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
ok

On Jul 29, 2009, at 11:25 AM, Cláudio Amaral wrote:

> Used some of previous code...
>
> I tried to make a polymorphic function and coupled an example...  
> this ended a little bit confusing, but as you can see, it makes all  
> iterations (check the printed indexes, reversed).
>
> The body behaviour is the tricky stuff to code, but in exchange it  
> is modular...
>
> Since I am an erlang newb, please correct anything you see as bad  
> programming
>
> Cláudio
>
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> -module(for_loop).
>
> -export([for/4, show/0]).
>
>
> for(BodyFunc, BodyArgs, StepFunc, {First, Last}) ->
>   for_(BodyFunc, BodyArgs, StepFunc, {First, Last}, First).
>
>
> for_(BodyFunc, BodyArgs, StepFunc, {_, LastTerm}, LastTerm) ->
>   BodyFunc(BodyArgs, LastTerm);
> for_(BodyFunc, BodyArgs, StepFunc, LimitsTuple, IndexTerm) ->
>   NextArgs = BodyFunc(BodyArgs, IndexTerm),
>   for_(BodyFunc, NextArgs, StepFunc, LimitsTuple,  
> StepFunc(IndexTerm)).
>
>
> show() ->
>   for( fun(A1,A2)->body1(A1,A2) end,
>    [{0,3}, [{1,0}], [{3,6},{1,2}]],
>    fun(I) -> I+1 end,
>    {0,3}
>   ).
>
>
> body1([ LimitsTuple, [{NLoop,II}|Rest], []],I) ->
>   print([ I | lists:map(fun({_,Snd}) -> Snd end, Rest) ]),
>   IndexInfo = [{NLoop,II}|Rest],
>   [ LimitsTuple, IndexInfo, []];
> body1([ LimitsTuple, [{NLoop,II}|Rest], [{X1,Xn}|XS]],I) ->
>   for( fun (A1,A2)->body1(A1,A2) end,
>    [ LimitsTuple, [ {NLoop+1,II}, {NLoop,I} | Rest ], XS],
>    fun(K) -> K+1 end,
>    {X1,Xn}
>   ),
>   IndexInfo = [{NLoop,II}|Rest],
>   [ LimitsTuple, IndexInfo, [{X1,Xn}|XS] ].
>
> print(Numbers) ->
>   io:format("indexes ~p~n", [Numbers]).
>
>
>  escreveu:
>> Regards,
>> Z.
>>
>>
>>> 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. See http://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
>>
>>
>
>
> ________________________________________________________________
> erlang-questions mailing list. See http://www.erlang.org/faq.html
> erlang-questions (at) erlang.org
>



More information about the erlang-questions mailing list