Benjamin Halsted // [bgh] todo, add something clever here.

18Mar/102

Erlang Programming Exercise: 3-5 (refactor)

I wasn't happy with how the flatten and concatenate functions turned out. They weren't taking advantage of tail call optimizations, so I rewrote the flatten function for fun. During my rewrite I also wanted to avoid using BIFs to work on my pattern matching. I wasn't sure if I would be able to match the head of a list, that was the head of a list. It worked out, here is the result:

flattenHelper(Dst, []) ->
        Dst;
flattenHelper(Dst, [[[]|HeadTail]|T]) ->
        flattenHelper(Dst, [HeadTail|T]);
flattenHelper(Dst, [[HeadTop|HeadTail]|T]) ->
        NewList1 = [HeadTail|T],
        NewList2 = [HeadTop|NewList1],
        flattenHelper(Dst, NewList2);
flattenHelper(Dst, [[]|T]) ->
        flattenHelper(Dst, T);
flattenHelper(Dst, [H|T]) ->
        flattenHelper([H|Dst], T);
flattenHelper(Dst, Item) ->
        [Item|Dst].

flatten(Lists) ->
        reverse(flattenHelper([], Lists)).

Cheers,
-Halzy

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Reddit
  • Twitter
Comments (2) Trackbacks (0)
  1. Heya-

    Found your blog while doing the exercises and searching for the answer to a question I had about 3.5 (writing flatten). Basically it says to use “concatenate to solve flatten” and even though I solved flatten similarly to the first way you did (my code below), I also didn’t use concatenate.

    What I’m OCDing on is I actually think his hint on using concatenate is wrong here, because erlang’s lists are untyped (so you never know if your dealing with a list of lists (which is what concatenate takes) until you navigate it).

    Regardless, great blog, and I’m going to start following your solutions to his book.

    ************************

    flatten([], Accum) ->
    Accum;
    flatten([H|[]], Accum) ->
    flatten(H, Accum);
    flatten([H|T], Accum) ->
    flatten(H, flatten(T, Accum));
    flatten(Val, Accum) ->
    [Val | Accum].

    flatten(List) ->
    flatten(List,[]).

  2. With restriction of using concatenate very similar function can be written:

    flatten2(List) -> reverse( flatten_helper(List,[]) ).
    flatten_helper([],Dst) -> Dst;
    flatten_helper([H|T],Dst) when is_list(H) -> flatten_helper( concatenate([H,T]), Dst );
    flatten_helper([H|T],Dst) -> flatten_helper( T, [H|Dst] ).

    you could avoid is_list by matching [[HH|HT]|T] and [[]|T] separately as in your example.

    I am now trying to break it :)


Leave a comment

(required)

No trackbacks yet.