Packages
tagged_with
0.1.0
A `with` that tags each clause's failure by name, so `else` can tell which step failed, even when two clauses fail with the same-looking value.
Current section
Files
Jump to
Current section
Files
tagged_with
README.md
README.md
# TaggedWith
A `with` that tags each clause's failure by name, so `else` can tell which
step failed even when two clauses can fail with the same-looking value.
Plain `with` matches `else` on whatever shape a clause's expression happens
to return. That breaks down when two clauses can produce the same-looking
value — say, `validate_email/1` and `validate_age/1` both returning
`{:error, :invalid}`. A pattern like `{:error, :invalid}` in `else` can't
tell you which one failed.
Tagging each clause fixes that — just `{name, pattern} <- {name, expr}` —
but it means writing the name twice per clause, by hand, every time:
```elixir
# what you'd otherwise write by hand
with {:email, :ok} <- {:email, validate_email(params)},
{:age, :ok} <- {:age, validate_age(params)} do
:ok
else
{:email, {:error, reason}} -> {:error, {:invalid_email, reason}}
{:age, {:error, reason}} -> {:error, {:invalid_age, reason}}
end
```
```elixir
# what you actually write
import TaggedWith
tagged_with email: :ok <- validate_email(params),
age: :ok <- validate_age(params) do
:ok
else
{:email, {:error, reason}} -> {:error, {:invalid_email, reason}}
{:age, {:error, reason}} -> {:error, {:invalid_age, reason}}
end
```
Each clause is `name: pattern <- expr` — no parens needed around
`pattern <- expr`, it parses fine as a keyword value. Write the bare
pattern you'd use in a plain `with` (`:ok`, `{:ok, value}`, ...) —
`tagged_with` adds the name to both sides for you, expanding into exactly
the hand-written form above, so `else` can still catch and tell apart the
failure from each line.
`else` is optional, exactly like in plain `with`. Without it, a failed
clause's tagged value (e.g. `{:email, {:error, reason}}`) comes back
directly — no exception, no extra behavior, since that's already how
`with` behaves without `else`.
## Installation
Add `tagged_with` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:tagged_with, "~> 0.1.0"}
]
end
```
Docs: <https://hexdocs.pm/tagged_with>