Experimenting with this code.
OK.try do
user <- fetch_user(1)
cart <- fetch_cart(1)
order = checkout(cart, user)
save_order(order)
end
Ok.with/1
supports an else block that can be used for handling error values.
OK.with do
a <- safe_div(8, 2)
_ <- safe_div(a, 0)
else
:zero_division -> # matches on reason
{:ok, :inf} # must return a new success or failure
end
The cart example above is equivalent to
with {:ok, user} <- fetch_user(1),
{:ok, cart} <- fetch_cart(1),
order = checkout(cart, user),
{:ok, order_id} <- save_order(order)
do
{:ok, order_id}
end
I have an implementation marked as beta as part of my OK project.
The Elixir with keyword has been very helpful for handling code with lots of branches, normally many error conditions. Such as the example above.
In the with example I find it is strange that the majority of my code my code lives in a list of arguments. It starts to get very lumpy if there are receive blocks or anonymous functions to get these values. Also in 90% of cases I am matching on an :ok
tuple so donāt want to repeat that.
For these reasons I have been using the alternative macro from OK. It is far more restrictive because it will only match on :ok
/:error
tuples. However I like the restriction because it means that no matter how complex the block it will also only return :ok
/:error
tuples.
I am not sure that try is the best name. Alternatives that I am considering are
- when, seams so make sense linguistically but already a keyword in elixir
- with, familiar to elixir users
- for, monadic for comprehension which is what this is but that might not be a very accessible term.
- try, As is, however it doesnāt catch errors so the name could be misleading