Fpo_small Franck PORCHER 1 post

Hi,

I’m just starting with Erlang, though very much accustomed to logic and functional programming. I feel this is a dream to invest for the future by going back to these most fecond programming styles.

I first opened the “Erlang Book” today (there is the “Camel book” to the Perl community) and I would like to reflect on style and efficiency.

I) Chapter 3 : odds_and_evens_acc/1

The author gives a solution that reverses the initial order of the argument, which can be voided out by applying a reverse/1 to the solution.

I’m convinced that the author made this choice deliberately over existing solutions that preserve the order right from the start, like odds_and_evens_acc_v2 :


odds_and_evens_acc_v2([]) -> {[],[]};
odds_and_evens_acc_v2([H|T]) ->
  {Odds,Evens} = odds_and_evens_acc_v2(T), 
  if
    H rem 2 =:= 0 -> {Odds,[H|Evens]};
    true          -> {[H|Odds],Evens}
  end.

And I wonder why ?

Is the style of dds_and_evens_acc_v2 considered acceptable by the seasoned Erlang developpers ? And if not, what would be the reason for this ?

How do these two versions compare regarding the efficiency criterion ?

II) Chapter 3 : filter/2

The question here is more about style.

I tend to consider the following version of filter/2 more readable and probably less efficient than the version given by the author.

Would this version be considered acceptable with respect to the “canons” of Erlang community ?


filter(P,[H|T]) -> append( cond3(P(H),[H],[]) , filter(P,T) );
filter(_,[])    -> [].

with cond2/3 defined as :


cond3(true,T,_) -> T;
cond3(_,_,F)    -> F.

Thank you in advance for any thoughtful comments.

Franck PORCHER

 
Alain_o_dea_small Alain O'Dea 35 posts

Hi Frank,

Thank you for this interesting post. It raises some very important questions and issues to keep in mind when writing Erlang code.

In the book odds_and_evens_acc/3 is written the way it is to allow tail-recursive optimization of the call stack. This sounds like a terrible reason to structure your code, but it is essential for scalability to arbitrarily large lists. It is a core concept to writing Erlang code.

Your odds_and_evens_acc_v2/1 makes use of the result of a recursive call within the recursive function. This forces the Erlang runtime to maintain a growing stack for each recursion (similar to Java/C++). This does not scale as it will eventually exhaust available memory for a large enough list.

Your version of filter/2 makes use of the result of a recursive call in the append/2 call. This means it will also not scale to large lists. The case-version of filter/2 in the book is much clearer than the doubly-recursive version in the book.

Your post raised some very important issues about Erlang coding. Thank you for posting :)

2 posts, 2 voices