dogweather
Is this a good pattern for handling a list of {:ok|:error} results?
I’m parsing input, returning the successfully parsing items, and logging the parse errors. (In this app, this is the behavior I want: continue working with successful parses, and a log file with the errata.)
processed_sections = map(raw_sections, &new_section/1)
reduce(processed_sections, [], fn e, acc ->
case e do
{:error, msg} ->
Logger.warn(msg)
acc
{:ok, section} ->
acc ++ [section]
end
end)
Is there some more canonical way of working through the {:ok|:error} results?
Most Liked
Sorc96
I tend to prefer functions other than custom reduce, so in this case, I would probably do someting like this:
{successful, failed} = Enum.split_with(processed_sections, &match?({:ok, _}, &1))
Enum.each(failed, fn {:error, msg} -> Logger.warn(msg) end)
successful
Seriously though, we need a standardized higher level way to work with :ok and :error tuples.
100phlecs
You can get rid of the case statement with anonymous function pattern matching:
i.e.
[{1, 2}, {3}, {4, 5}]
|> Enum.reduce(0, fn
{x, y}, acc -> acc + x + y
{x}, acc -> acc + x
end)
or in your case
processed_sections = map(raw_sections, &new_section/1)
reduce(processed_sections, [], fn
{:error, msg}, acc ->
Logger.warn(msg)
acc
{:ok, section}, acc ->
acc ++ [section]
end)
al2o3cr
This can be golfed down even further by using Enum.flat_map to express the “map, but only keep some of them” idiom:
raw_sections
|> map(&new_section/1)
|> Enum.flat_map(fn
{:ok, result} -> [result]
{:error, msg} -> Logger.warn(msg); []
end)
Monad enthusiasts should be able to spot Result being transformed into Option there ![]()
hst337
There are several ways to do this, but there is no “canonical” way.
Your solution has a problem with ++ operator, which makes this whole solution be O(n^2) complexity. I’d suggest prepending to the head and then reversing the result (or using Enum.flat_map)
awerment
Taking the opportunity for some bike shedding
… If you‘re not using the intermediate values, you could do it with some pipes:
raw_sections
|> map(&new_section/1)
|> reduce([], fn
{:error, msg}, acc ->
Logger.warn(msg)
acc
{:ok, section}, acc ->
[section | acc]
end)
|> reverse()








