Pipehammer v0.1.1 Pipehammer View Source
Pipehammer, the simplest pipeline management.
You may now declare regular functions, and Pipehammer will write boilerplate for you.
Example:
defpipe safe_div(x, 0) do
{:error, :division_by_zero}
end
defpipe safe_div(x, y) do
{:ok, x / y}
end
This will define a function having this type signature:
@spec safe_div(any | {:ok, any} | {:error, any} ::
{:ok, any} |
{:error, :division_by_zero} |
{:error, any }
12 |> safe_div(6) # => {:ok, 2.0}
12 |> safe_div(0) # => {:error, :division_by_zero}
{:ok, 12} |> safe_div(6) # => {:ok, 2.0}
{:error, :not_a_number} |> safe_div(6) # => {:error, :not_a_number}
This has immediate application in building pipelines:
defp issue_referral_voucher(account_id, referrer_reference) do
find_account(account_id)
|> set_account_referrer(referrer_reference)
|> issue_referral_voucher()
|> create_activity()
|> publish_event()
|> handle_error(fn e ->
{:error, "bad error"}
end)
end
You can still use with
macro if you wish:
defp issue_referral_voucher(account_id, referrer_reference) do
with {:ok, acc} <- find_account(account_id),
{:ok, acc} <- set_account_referrer(acc, referrer_reference),
{:ok, vou} <- issue_referral_voucher(acc),
{:ok, act} <- create_activity(vou) do
publish_event(act)
else
{:error, e} -> {:error, "bad error"}
end
end
You can still compose the functions as usual:
set_account_referrer(find_account(account_id), referrer_reference)
Error handling
Pipe functions are expected to return {:error, e}
tuples in error cases.
If additional information is required, consider wrapping it into a tuple:
{:error, {:foo, :bar}}
If pipe function returns anything other than {:ok, any} | {:error, any}
the behaviour of Pipehammer is undefined (means, the pipeline will crash in production))
What boilerplate to expect:
defpipe partial(x, y) when is_integer(x) do
{:ok, x + y}
end
Will create these functions, in order:
def partial({:error, e}, _) do
{:error, e}
end
def partial({:ok, x}, y) when is_integer(x) do
partial(x, y)
end
def partial(x, y) when is_integer(x) do
{:ok, x + y}
end
Note that error case intentionally does not have guards, as it does not care what you pass into the function, as long as 1st argument was an error. This logic is essential to chaining the steps.
Pipehammer is smart to eliminate duplicate error declarations:
defpipe foo(x, 0) do
{:ok, x}
end
defpipe foo(x, 1) do
{:ok, x}
end
This will still write one error clause:
def foo({:error, e}, _) do
{:error, e}
end
Link to this section Summary
Functions
Alternative piping: it first step fails, try another one.
Declares function clauses that will handle nil
, {:ok, _}
, {:error, _}
in addition to its main clause.
Handles errors, but leaves ok tuples intact
Link to this section Functions
Alternative piping: it first step fails, try another one.
Declares function clauses that will handle nil
, {:ok, _}
, {:error, _}
in addition to its main clause.
Handles errors, but leaves ok tuples intact