Last Updated: November 19, 2020
· martinrehfeld

Erlang List Comprehension Gotcha

Here's a little quiz question for you: What is the result of this list comprehension in Erlang?

[ {A,B} || {A,B} <- [1,2,{3,4},[5,6]] ]

A.) [{1,2}, {3,4}, {5,6}]

B.) badmatch error

C.) [{3,4}]

Who said A? You are kidding, right? Go re-read "Learn You Some Erlang".

But what about choices are B vs. C. I must admit, I always assumed B would be correct but as a matter of fact, it is actually C. Huh?

Please note: An Erlang list comprehension will silently filter out any values that can not be matched against the expression left of the arrow.

This is especially noteworthy if you are (ab)using list comprehensions for side effects, take this unit test for example:

[ ?assertEqual(A, B+1) || {A, B} <- fetch_some_list_of_results() ]

Now let's assume fetch_some_list_of_results() actually returns [error, error, error]. The test would still pass as no assertion ever gets executed. Watch out!

Even better: Write the above test like this instead to get a badmatch error in case your assumption about the results is wrong:

lists:foreach(fun ({A, B}) ->
                      ?assertEqual(A, B+1)
              end, fetch_some_list_of_results())

Related protips:

Flatten a list of lists in one line in Python