Solution: library to do pattern-matching with general ok/error types in case/with statements -- v1.0.1

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’s with but not completely (I think?), which is also subject to above caveat.
  • OK has a wrapper called OK.try which is sort of like OK.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 or with 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 and with 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! :smile:

4 Likes