README.md

![Solution](brand/logo_text.png)

`Solution` is a library to help you with working with ok/error-tuples by exposing special matching macros.

[![hex.pm version](https://img.shields.io/hexpm/v/solution.svg)](https://hex.pm/packages/solution)
[![Build Status](https://travis-ci.org/Qqwy/elixir_solution.svg?branch=master)](https://travis-ci.org/Qqwy/elixir_solution)
[![Inline docs](http://inch-ci.org/github/qqwy/elixir_solution.svg)](http://inch-ci.org/github/qqwy/elixir_solution)


## Installation

You can install Solution by adding `solution` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:solution, "~> 0.1.0"}
  ]
end
```

## Examples

The following example snippets assume that you run 
```elixir
require Solution
import Solution
```

(although of course, `Solution` is also fully usable without importing it.)

### Guards

`Solution` exposes three guard-safe functions: `is_ok(x)`, `is_error(x)` and `is_okerror(x)`

- `ok(x)` will match `:ok`, `{:ok, _}`, `{:ok, _, _}`, `{:ok, _, _, __}` and any longer tuple whose first element is `:ok`.
- `error(x)` will match `:error`, `:undefined` `{:error, _}`, `{:error, _, _}`, `{:error, _, _, __}` and any longer tuple whose first element is `:error`.
- `okerror(x)` matches both of these.

Solution also exposes versions of these that take a 'minimum-length' as second argument. A length of `0` works jus the same as above versions. Longer lengths only match tuples that have at least that many elements (as well as starting with the appropriate tag).

### SCase

`Solution.scase`works like a normal `case`-statement,
but will expand `ok()`, `error()` and `okerror()`macros to the left side of `->`.

```elixir
 scase {:ok, 10} do
  ok() -> "Yay!"
  _ -> "Failure"
  end
#=> "Yay!"
```


You can also pass arguments to `ok()`, `error()` or `okerror()` which will then be bound and available
to be used inside the case expression:

```elixir
 scase {:ok, "foo", 42} do
 ok(res, extra) ->
      "result: \#{res}, extra: \#{extra}"
      _ -> "Failure"
    end
#=> "result: foo, extra: 42"
```

Note that for `ok()` and `error()`, the first argument will match the first element after the `:ok` or `:error` tag.
On the other hand, for `okerror()`, the first argument will match the tag `:ok` or `:error`.

### SWith

`Solution.swith` works like a normal `with`-statement,
but will expand `ok()`, `error()` and `okerror()` macros to the left side of `<-`.


```elixir
 x = {:ok, 10}
 y = {:ok, 33}
 swith ok(res) <- x,
       ok(res2) <- y do
      "We have: \#{res} \#{res2}"
    else
      _ -> "Failure"
  end
#=> "We have: 10 33"
```


You can also pass arguments to `ok()`, `error()` or `okerror()` which will then be bound and available
to be used inside the rest of the `swith`-expression:

```elixir
 x = {:ok, 10}
 y = {:error, 33}
 z = {:ok, %{a: 42}}
 swith ok(res) <- x,
       error(res2) <- y,
       okerror(tag, metamap) <- z,
     %{a: val} = metamap do
       "We have: \#{res} \#{res2} \#{tag} \#{val}"
   else
       _ -> "Failure"
   end
#=> "We have: 10 33 ok 42"
```

Note that for `ok()` and `error()`, the first argument will match the first element after the `:ok` or `:error` tag.
On the other hand, for `okerror()`, the first argument will match the tag `:ok` or `:error`.


## Documentation

Full documentation can be found at [https://hexdocs.pm/solution](https://hexdocs.pm/solution).


## Changelog

- 0.1.0 - Initial version