2
votes

I use list comprehension for transforming database rows from the list of tuples to the list of maps. One day I have added some new column into my database table and forget to change the code everywhere. And because of that I discovered a strange effect: database rows become an empty list.

Example of code in erl console:

> DbRows = [{1, 1, 1}, {2, 2, 2}].
[{1,1,1},{2,2,2}]
> [#{<<"col1">> => Col1, <<"col2">> => Col2} ||{Col1, Col2} <- DbRows].
[]

Why Erlang does not generate exception error: no match of right hand side value in this case?

Is this code OK, or some other syntax is preferred for performing such data transforming?

2

2 Answers

5
votes

Erlang does not generate any exception because that's a right syntax. Generator {Col1, Col2} <- DbRows is a filter in the same time. So any element that does not match pattern just skipped. In your case I would do something like that:

-define(FIELDS, [id, some1, some2]).
DbRows = [{1, 1, 1}, {2, 2, 2}].
Prepare = fun(X) ->
    maps:from_list(lists:zip(?FIELDS, tuple_to_list(X)))
end.
[ Prepare(Row) || Row <- DbRows].

And when you add new field you need to add that field in the macros.

1
votes

I don't like this "feature", since in my experience it tends to mask bugs, but nikit's answer is correct about the reason for the result you see.

You can get the exception by moving the pattern matching to the left side of the list comprehension:

[ case Row of {Col1, Col2} -> #{<<"col1">> => Col1, <<"col2">> => Col2} || Row <- DbRows ]