Crowdhailer
OK: Elegant error handling for elixir pipelines. Version 1.0 released
I have been updating a library that allows you to pipe between functions that use the erlang result tuple convention.
Assuming you have a double function with the spec double(int()) :: {:ok, int()} and safe dividing function. safe_div(int(), int()) :: {:ok, int()} | {:error, term()}.
Ok now can be used to create a pipeline that looks very much like the native pipe operator.
iex> {:ok, 6} ~>> safe_div(3) ~>> double
{:ok, 4.0}
iex> {:ok, 6} ~>> safe_div(0) ~>> double
{:error, :zero_division}
I have opened a pull request for this new version and pushed a release candidate. Hopefully it’s now interesting to people.
Most Liked
Crowdhailer
OvermindDL1
I’d recommend Ok as well as it is common vernacular now. However, OK is correct as it is short for (what is considered by etymologists(sp?)) Oll Korrekt, a vernacular of “All Correct” popularized in 1840’s New York (told to me by google ^.^). 
So, although I tend to use Ok myself, technically OK is correct. 
brainbag
Although I love the concept, I found some issues with the implementation in practice for user errors, which is where this pattern is intended to be used. In particular:
- not all functions return the same shape.
- one of my own functions that returned
{:ok, :name, %metadata{}}which wouldn’t fit. - some of the Elixir functions I needed didn’t return an error tuple.
Map.fetch/2for example just returns:error.
- one of my own functions that returned
- Although it was nice to break free when an error happened, I found error handling unnecessarily difficult because rather than handling the
:errorin context, I was doing it somewhere down the line. Often this meant I had to reconstruct context in order to provide a meaningful message to the UI.
To resolve #1, I decided to change how it measured the results and tested either the result == :error || elem(result, 0) == :error, and any other result was just passed through. This worked better for me and allowed for the shapes to be different. It could be expanded to capture more errors, but it still assumes that it would know all error conditions.
Overall, after using it for a while, it felt more like I was using try/catch or GOTO for flow control, which I am not fond of. I found it to basically be just a prettier but less comprehensible/usable version of with.
I still love the idea of a flow chart for flow control, though!
ibgib
Very concise syntax for tagged fluent builder statements!
def instance(identity_ib_gibs, dest_ib, opts) do
{:ok, identity_ib_gibs}
~>> TB.plan("[src]", opts)
~>> TB.add_fork("fork1", dest_ib)
~>> TB.add_rel8("rel8_2_src", "[plan.src]", ["instance_of"])
~>> TB.yo
end
And I’m planning on more, slightly longer factory methods just like these and this helps clean things up very nicely. Thanks! 







