An excellent question. I most certainly did!
Solution
is meant to be more general and more lightweight/idiomatic in its approach.
Let’s compare it with the six other commonly mentioned libraries that work with ok/error tuples:
Comparing it to the ok
library:
- OK requires ok/error tuples to always exactly have two elements (the first being
:ok
or:error
, the second being a value). This means that plain:ok
or:error
are not handled, nor are results like{:ok, value, meta}
which are relatively common in production Elixir (c.f. Ecto Multi). - OK introduces a new ‘keyword’ called
OK.for
which sort of takes the place of Elixir’swith
but not completely (I think?), which is also subject to above caveat. - OK has a wrapper called
OK.try
which is sort of likeOK.for
but wraps it in an extra try/rescue block (I think?). - OK contains a couple of custom operators to allow ‘monadic piping’.
Solution’s swith
and scase
statements on the other hand work 1:1 like the built-in counterparts, except that you can add the ok(...)
and error(...)
macros at the LHS of the matches to match any ok/error tuple that has at least the required length. I believe that the library therefore has much less of a learning curve and much less mental overhead.
Comparing it to the result
library:
- Result has a bunch of monad-inspired functions, but no overloaded
case
orwith
statements. - Just like OK, Result only accepts exactly the format
{:ok, value}
/{:error, problem}
.
Comparing it to the exceptional
library:
- Exceptional has features to declaw exceptions and turn them into plain structs or possibly ok/error tuples, and reraise them later. Handling exceptions is not a design goal of
Solution
, so it does not have this functionality. - Exceptional also has custom ‘monadic piping’ operators.
-
Handling different kinds of tagged tuples is not a design goal of Exceptional, so it does not have functionality to work with these datatypes (other than a basic ‘normalization’ conversion, which also does not handle ok/error tuples with more than one value inside).EDIT: It’s slightly more nuanced than that. see this follow-up.
Comparing it to the towel
library:
- Towel also takes the approach of a ‘monadic pipeline’. Not with special syntax this time, but using a couple of functions (that are probably part of your global namespace since it advocates to
use Towel
). - Towel does not have support for values of the type
:ok
/:error nor for
{:ok, multiple, things}`. - Towel’s last commit was more than two years ago.
Comparing it to the ok_jose
library:
- OkJose overloads
|>
to work differently for ok/error tuples. - OkJose allows you to create other overloaded versions of
|>
. - OkJose does not have support for values of the type
:ok
/:error nor for
{:ok, multiple, things}`. - OkJose’s last commit was more than two years ago, and the README mentions that it was made before
with
was available in Elixir.
So the Tl;Dr is that Solution has a slightly different approach to these libraries:
- It strives to support all possible ok/error values that are used in practice: Not only the two-element tuple versions, but also the single atoms
:ok
and:error
, as well as the versions with more than two elements like{:ok, data, metadata}
. - It strives to be lightweight by using the existing
case
andwith
syntax, rather than adding variants of the pipe-operator and/or require an understanding of monads to be used successfully. - It is focused on working with ok/error tuples. It does not deal with exceptions or other kind of failure indications.
I hope that answers your question!