Существует ли стандартная практика при работе со списком кортежей ошибок? - PullRequest
0 голосов
/ 22 марта 2020

В моем приложении я хочу применить функции к списку значений.

Поскольку функции работают с веб-API или базой данных, я должен проверять наличие ошибок. Можно было бы вернуть кортеж {:ok, result} или {:error, reason}, что привело бы к списку указанных кортежей.

Я мог бы проверить этот список с помощью функции, подобной приведенной ниже. Тем не менее, это кажется очень неуклюжим, и мне интересно, есть ли более элегантное решение. Может быть использование исключений?

def check_errors(lst) do
    if Enum.any?(lst, fn {s, _} -> s == :error end) do
        errors = Enum.filter(lst, fn {s, b} -> s == :error end)
                    |> Enum.map(fn {s, b} -> b end)
        IO.puts("Found Errors: ")
        IO.inspect(errors)
        System.halt(0)
    else
        lst
    end
end

1 Ответ

1 голос
/ 22 марта 2020

Есть много разных способов, но в описанном сценарии Enum.split_with/2 ваш друг.

[{:ok, 1}, {:error, 2}, {:ok, 3}]
|> Enum.split_with(fn {:error, _} -> true; _ -> false end)
|> case do
  {[], oks} ->
     oks
  {errors, _} ->
     errors
     |> Enum.map(&elem(&1, 1))
     |> IO.inspect(label: "Found errors")
end

Также швейцарский нож Enum.reduce/3 может использоваться как во всех других случаях, когда нужно свернуть список.

[{:ok, 1}, {:error, 2}, {:ok, 3}]
|> Enum.reverse() # needed to prepend below
                  # preserving the original order
|> Enum.reduce(%{errors: [], oks: []}, fn
  {:error, error}, acc ->
    %{acc | errors: [error | acc.errors]}
  {:ok, ok}, acc ->
    %{acc | oks: [ok | acc.oks]}
end) 
#⇒ %{errors: [2], oks: [1, 3]}

Как правильно сказал @Daniel в комментариях, «Используются исключения в эликсире как механизм отправки ошибки родительскому процессу и должен использоваться только при наличии ошибки разрыва приложения. ”

...