Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,026 | Comments: 44,842

filter by tags archive

Sometimes imperative is so much easier

time to read 3 min | 472 words

Take a look at the following Erlang function:

count_promises(Id, N, {_, PromisesQueue}) ->
    rec_count_promises(0, Id, N, PromisesQueue).

rec_count_promises(Count, _, _, []) ->
rec_count_promises(Count, Id, N, [{Id, N, _, _} | RestQueue]) ->
    rec_count_promises((Count + 1), Id, N, RestQueue);
rec_count_promises(Count, Id, N, [_ | RestQueue]) ->
    rec_count_promises(Count, Id, N, RestQueue).

I am reading a codebase full of this sort of things, and it is really painful. I keep thinking back to how I would do it in C#:

public int CountPromises(int id, int n, Tuple<List<Record>, List<Record>> phase1)
     int count=0;
     foreach(var record in phase1.Item2)
            if(record.Id == id && record.N == n)
                   count ++;
     return count ;

Yet that is imperative, and involve mutating state. I agree, it is a huge improvement, but it can be made both functionally safe and easier to read:

phase1.Items2.Count(record => record.Id == id && record.N == n);

As I said, I am currently going through a codebase full of these sort of functions, and it is painful, annoying and irritating. I am not experienced enough with Erlang to be able to tell conclusively if this is idiomatic Erlang code, but I think so.


Paul Cowan

Did the Erlang code come from couchdb?

If so, I would be curious to know what benefit there is in rewriting couchdb on another platform?

Andrew Davey

Writing out the recursion and pattern matching for this function sure feels like a waste of time.

It seems to me that the Erlang code should be re-factored to make use of higher level functions, like "filter".

Demis Bellot

Yeah it's hard to see how this can can be more readable in anyone's mind. I'm aware the mathematical mind works differently and prefers the purity of functional programming without side-effects but does it work this different?

IMHO readability of code is just as important as succinctness, i.e. there's no point having really tight code with low signal/noise ratio if it takes others longer to scan and understand a page of code.


This is horrible functional programming style. I'm not a Erlang wizard, so this is how I would write the function in Haskell:

countPromises id n = length . filter ((id', n') -> id' == id && n' == n) . snd

Much better! If you want it to look like C# you can also define:

count p = length . filter p

countPromises id n = count ((id', n') -> id' == id && n' == n) . snd

If you use GHC, all the intermediate lists wil be fused away, so this will actually compile into the tight imperative loop you wrote above.


This cannot be idiomatic erlang code because it would mean that most erlang programmers are not very smart. That is hard to believe.


Oh. I thought you said "idiotic" Erlang code.

I think yes, it is.


countpromises(Id, N, {, PromisesQueue}) ->

lists:foldr(fun(X,ACC) -> {I,NN,,} = X, if I==Id , NN==N -> ACC+1; true -> ACC end end , 0, PromisesQueue).


Probably no comments in the mess either.

Igor K.

countpromises(Id, N, {, PromisesQueue}) ->

length(lists:filter(fun(X, Y, _, _}) -> X =:= Id andalso Y =:= N end, PromisesQueue)).


Doesnt look idiomatic functional programming at all, it looks like a mechanical conversion of an imperative loop with mutating state to a recursive function call with accumulators. Which is basic functional programming 101, but in general once the user learns that they can do this relieably, they then move on to composing simple functions over lists to accomplish the same goal. Not sure its possible that maybe there is some performance gain in the erlang implementation if you feel this was programmed by advanced functional programmers. A lot of times when performance is taken into account, an advanced programmer has to strip out all the nice functional patterns and put in some worst of both worlds imperative/functional chimera

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats