3 ms·
Ah, I missed the `or_else` function. Normally, you'd do something like: with ... do ... else {:error, _} = err -> # ... handle err
by ashton314 5y ago
Ah, I missed the `or_else` function.
Normally, you'd do something like:
with ... do
...
else
{:error, _} = err ->
# ... handle error here ...
err # propagate the error
end
But if you need to handle errors at different points of the pipeline differently, it can get pretty unwieldy. (I've wrapped the function calls in a tuple like
with {:step_1, {:ok, value}} <- {:step_1, fn_call(...)}
so I could dispatch on that tuple in the `else` block, but I think your solution is cleaner than that—especially if you need some kind of recovery that lets you go on with the normal computation. :) So if that's what you need to work with, then I don't think you're doing it wrong.
- linkdd 5y agowith {:step_1, {:ok, value}} <- {:step_1, fn_call(...)} I also use this pattern a lot :) To be fair, I'm not using this library everywhere. Only when case/with become hard to read. Or when I have a pipeline like: fetch_list_of_resources() |> Result.or_else(fn _ -> [] end) # ignore the error |> Stream.filter(&check_condition/1) |> Stream.map(&delete_resource/1) |> Result.collect() # fails at the first error |> Result.unwrap!() # raise if error ASAP |> Enum.map(&log_deleted_resource/1) It is IMHO easier to read, refactor and debug (with some well-placed IO.inspect). Before this library, I was copy/pasting `then(fn ... end)`. I don't like to repeat myself :)