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
:okor:error, the second being a value). This means that plain:okor:errorare 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.forwhich sort of takes the place of Elixir’swithbut not completely (I think?), which is also subject to above caveat. - OK has a wrapper called
OK.trywhich is sort of likeOK.forbut 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
caseorwithstatements. - 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
withwas 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
:okand:error, as well as the versions with more than two elements like{:ok, data, metadata}. - It strives to be lightweight by using the existing
caseandwithsyntax, 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! ![]()






















